torch.linalg.svd#
- torch.linalg.svd(A, full_matrices=True, *, driver=None, out=None)#
Computes the singular value decomposition (SVD) of a matrix.
Letting be or , the full SVD of a matrix , if k = min(m,n), is defined as
其中 , 是当 是复数时的共轭转置,当 是实数时的转置。矩阵 , (因此 )在实数情况下是正交的,在复数情况下是酉的。
当 m > n (resp. m < n) 时,我们可以去掉 U (resp. V) 的最后 m - n (resp. n - m) 列,以形成约简 SVD
其中 。在这种情况下, 和 也具有标准正交列。
支持 float、double、cfloat 和 cdouble 数据类型。还支持矩阵批处理,如果
A
是矩阵批处理,则输出具有相同的批处理维度。返回的分解是一个命名元组 (U, S, Vh),对应于上面提到的 、、。
奇异值按降序返回。
full_matrices
参数选择全 SVD(默认)或约简 SVD。在 CUDA 上,可以使用
driver
关键字参数来选择用于计算 SVD 的算法。驱动程序的选择是在精度和速度之间的权衡。如果
A
是良态的(其 条件数不是太大),或者您不介意一些精度损失。对于一般矩阵:‘gesvdj’(雅可比法)
如果
A
是高瘦矩阵或宽扁矩阵(m >> n 或 m << 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):, :] 的梯度,因为这些向量可以是相应子空间的任意基。警告
返回的张量 U 和 V 并非唯一,并且相对于
A
也不连续。由于这种非唯一性,不同的硬件和软件可能计算出不同的奇异向量。这种非唯一性是由于将一对奇异向量 乘以-1(实数情况)或乘以 (复数情况)会产生另外两个有效的奇异向量,从而引起了此非唯一性。因此,损失函数不应依赖于此 的量,因为它没有定义好。在计算此函数梯度时,会对复数输入进行此检查。因此,当输入为复数且位于 CUDA 设备上时,此函数梯度的计算会使该设备与 CPU 同步。
警告
使用 U 或 Vh 计算的梯度仅在
A
没有重复奇异值时才是有限的。如果A
是矩形的,此外,零也不能是其奇异值之一。此外,如果任何两个奇异值之间的距离接近零,梯度将是数值不稳定的,因为它取决于奇异值 通过 的计算。在矩形情况下,当A
具有较小的奇异值时,梯度也将是数值不稳定的,因为它还取决于 的计算。另请参阅
torch.linalg.svdvals()
仅计算奇异值。与torch.linalg.svd()
不同,svdvals()
的梯度始终是数值稳定的。请参阅
torch.linalg.eig()
,它计算矩阵的另一种谱分解。特征值分解仅适用于方阵。请参阅
torch.linalg.eigh()
,它是一个(更快的)用于计算厄米特矩阵和对称矩阵特征值分解的函数。请参阅
torch.linalg.qr()
,它实现了另一种(快得多)适用于通用矩阵的分解。- 参数
- 关键字参数
- 返回
命名元组 (U, S, Vh),对应于上面提到的 、、。
S 始终是实数值,即使
A
是复数。它也将按降序排序。U 和 Vh 将具有与
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)