评价此页

torch.linalg.svd#

torch.linalg.svd(A, full_matrices=True, *, driver=None, out=None)#

Computes the singular value decomposition (SVD) of a matrix.

Letting K\mathbb{K} be R\mathbb{R} or C\mathbb{C}, the full SVD of a matrix AKm×nA \in \mathbb{K}^{m \times n}, if k = min(m,n), is defined as

A=Udiag(S)VHUKm×m,SRk,VKn×nA = U \operatorname{diag}(S) V^{\text{H}} \mathrlap{\qquad U \in \mathbb{K}^{m \times m}, S \in \mathbb{R}^k, V \in \mathbb{K}^{n \times n}}

其中 diag(S)Km×n\operatorname{diag}(S) \in \mathbb{K}^{m \times n}, VHV^{\text{H}} 是当 VV 是复数时的共轭转置,当 VV 是实数时的转置。矩阵 UU, VV(因此 VHV^{\text{H}})在实数情况下是正交的,在复数情况下是酉的。

m > n (resp. m < n) 时,我们可以去掉 U (resp. V) 的最后 m - n (resp. n - m) 列,以形成约简 SVD

A=Udiag(S)VHUKm×k,SRk,VKn×kA = U \operatorname{diag}(S) V^{\text{H}} \mathrlap{\qquad U \in \mathbb{K}^{m \times k}, S \in \mathbb{R}^k, V \in \mathbb{K}^{n \times k}}

其中 diag(S)Kk×k\operatorname{diag}(S) \in \mathbb{K}^{k \times k}。在这种情况下,UUVV 也具有标准正交列。

支持 float、double、cfloat 和 cdouble 数据类型。还支持矩阵批处理,如果 A 是矩阵批处理,则输出具有相同的批处理维度。

返回的分解是一个命名元组 (U, S, Vh),对应于上面提到的 UUSSVHV^{\text{H}}

奇异值按降序返回。

full_matrices 参数选择全 SVD(默认)或约简 SVD。

在 CUDA 上,可以使用 driver 关键字参数来选择用于计算 SVD 的算法。驱动程序的选择是在精度和速度之间的权衡。

  • 如果 A 是良态的(其 条件数不是太大),或者您不介意一些精度损失。

    • 对于一般矩阵:‘gesvdj’(雅可比法)

    • 如果 A 是高瘦矩阵或宽扁矩阵(m >> nm << n):‘gesvda’(近似法)

  • 如果 A 不是良态的或精度很重要:‘gesvd’(基于 QR)

默认情况下(driver= None),我们调用 ‘gesvdj’,如果失败,则回退到 ‘gesvd’

numpy.linalg.svd 的区别

  • numpy.linalg.svd 不同,此函数始终返回三个张量的元组,并且不支持 compute_uv 参数。请使用 torch.linalg.svdvals()(它仅计算奇异值),而不是 compute_uv=False

注意

full_matrices= True 时,将忽略相对于 U[…, :, min(m, n):]Vh[…, min(m, n):, :] 的梯度,因为这些向量可以是相应子空间的任意基。

警告

返回的张量 UV 并非唯一,并且相对于 A 也不连续。由于这种非唯一性,不同的硬件和软件可能计算出不同的奇异向量。

这种非唯一性是由于将一对奇异向量 uk,vku_k, v_k乘以-1(实数情况)或乘以 eiϕ,ϕRe^{i \phi}, \phi \in \mathbb{R}(复数情况)会产生另外两个有效的奇异向量,从而引起了此非唯一性。因此,损失函数不应依赖于此 eiϕe^{i \phi} 的量,因为它没有定义好。在计算此函数梯度时,会对复数输入进行此检查。因此,当输入为复数且位于 CUDA 设备上时,此函数梯度的计算会使该设备与 CPU 同步。

警告

使用 UVh 计算的梯度仅在 A 没有重复奇异值时才是有限的。如果 A 是矩形的,此外,零也不能是其奇异值之一。此外,如果任何两个奇异值之间的距离接近零,梯度将是数值不稳定的,因为它取决于奇异值 σi\sigma_i 通过 1minijσi2σj2\frac{1}{\min_{i \neq j} \sigma_i^2 - \sigma_j^2} 的计算。在矩形情况下,当 A 具有较小的奇异值时,梯度也将是数值不稳定的,因为它还取决于 1σi\frac{1}{\sigma_i} 的计算。

另请参阅

torch.linalg.svdvals() 仅计算奇异值。与 torch.linalg.svd() 不同,svdvals() 的梯度始终是数值稳定的。

请参阅 torch.linalg.eig(),它计算矩阵的另一种谱分解。特征值分解仅适用于方阵。

请参阅 torch.linalg.eigh(),它是一个(更快的)用于计算厄米特矩阵和对称矩阵特征值分解的函数。

请参阅 torch.linalg.qr(),它实现了另一种(快得多)适用于通用矩阵的分解。

参数
  • A (Tensor) – 形状为 (*, m, n) 的张量,其中 * 是零个或多个批处理维度。

  • full_matrices (bool, optional) – 控制是计算全 SVD 还是约简 SVD,以及返回的张量 UVh 的形状。默认值:True

关键字参数
  • driver (str, optional) – 要使用的 cuSOLVER 方法的名称。此关键字参数仅适用于 CUDA 输入。可用选项为:Nonegesvdgesvdjgesvda。默认值:None

  • out (tuple, optional) – 三个张量的输出元组。如果为 None 则忽略。

返回

命名元组 (U, S, Vh),对应于上面提到的 UUSSVHV^{\text{H}}

S 始终是实数值,即使 A 是复数。它也将按降序排序。

UVh 将具有与 A 相同的 dtype。左/右奇异向量将由 U 的列和 Vh 的行分别给出。

示例

>>> A = torch.randn(5, 3)
>>> U, S, Vh = torch.linalg.svd(A, full_matrices=False)
>>> U.shape, S.shape, Vh.shape
(torch.Size([5, 3]), torch.Size([3]), torch.Size([3, 3]))
>>> torch.dist(A, U @ torch.diag(S) @ Vh)
tensor(1.0486e-06)

>>> U, S, Vh = torch.linalg.svd(A)
>>> U.shape, S.shape, Vh.shape
(torch.Size([5, 5]), torch.Size([3]), torch.Size([3, 3]))
>>> torch.dist(A, U[:, :3] @ torch.diag(S) @ Vh)
tensor(1.0486e-06)

>>> A = torch.randn(7, 5, 3)
>>> U, S, Vh = torch.linalg.svd(A, full_matrices=False)
>>> torch.dist(A, U @ torch.diag_embed(S) @ Vh)
tensor(3.0957e-06)