快捷方式

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 为实数时是转置。矩阵 UUVV (以及 VHV^{\text{H}}) 在实数情况下是正交矩阵,在复数情况下是酉矩阵。

m > n (或 m < n) 时,我们可以丢弃 U 的后 m - n 列 (或 V 的后 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 dtypes 输入。也支持批次矩阵输入,如果 A 是一个批次矩阵,则输出具有相同的批次维度。

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

奇异值按降序返回。

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

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

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

    • 对于一般矩阵:‘gesvdj’ (Jacobi 方法)

    • 如果 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 是矩形矩阵,则额外要求零也不能是其奇异值之一。此外,如果任意两个奇异值之间的距离接近于零,则梯度在数值上会不稳定,因为它依赖于通过计算 1minijσi2σj2\frac{1}{\min_{i \neq j} \sigma_i^2 - \sigma_j^2} 中的奇异值 σi\sigma_i。在矩形矩阵的情况下,当 A 具有较小的奇异值时,梯度在数值上也会不稳定,因为它也依赖于计算 1σi\frac{1}{\sigma_i}

另请参阅

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

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

torch.linalg.eigh() 是一个 (更快地) 函数,用于计算 Hermitian 矩阵和对称矩阵的特征值分解。

torch.linalg.qr() 是另一种 (快得多地) 分解,适用于一般矩阵。

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

  • full_matrices (bool, optional) – 控制计算完全 SVD 还是约减 SVD,因此也决定了返回张量 UVh 的形状。默认值: True

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

  • out (tuple, optional) – 包含三个张量的输出元组。如果为 None 则忽略。默认值: 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 全面的开发者文档

查看文档

教程

获取面向初学者和高级开发者的深度教程

查看教程

资源

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

查看资源