快捷方式

torch.linalg.svd

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

计算矩阵的奇异值分解 (SVD)。

K\mathbb{K}R\mathbb{R}C\mathbb{C},矩阵 AKm×nA \in \mathbb{K}^{m \times n} 的**完整 SVD**,如果 k = min(m,n),则定义为

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(分别为 m < n)时,我们可以去掉 U(分别为 V)的最后 m - n(分别为 n - m)列,形成**缩减 SVD**

A=Udiag(S)VHUKm×k,SRk,VKk×nA = 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}^{k \times n}}

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

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

返回的分解是一个命名元组 (U, S, Vh),分别对应于上述公式中的 UU, SS, VHV^{\text{H}}.

奇异值按降序返回。

参数 full_matrices 用于选择完整的 (默认) 或简化的 SVD。

在使用 cuSOLVER 后端的 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 同步。

警告

仅当A没有重复的奇异值时,使用UVh计算的梯度才是有限的。如果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 (张量) – 形状为(*, m, n)的张量,其中*为零个或多个批处理维度。

  • full_matrices (布尔值, 可选) – 控制是否计算完整或简化的SVD,以及由此返回的张量UVh的形状。默认值:True

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

  • out (元组, 可选) – 三个张量的输出元组。如果为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)

文档

访问 PyTorch 的全面开发者文档

查看文档

教程

获取适合初学者和高级开发人员的深度教程

查看教程

资源

查找开发资源并获得问题的解答

查看资源