torch.svd¶
- torch.svd(input, some=True, compute_uv=True, *, out=None)¶
计算矩阵或矩阵批次的奇异值分解。奇异值分解表示为一个命名元组 (U, S, V),使得
input。 其中 是实数输入的 V 的转置, 以及复数输入的 V 的共轭转置。 如果input是矩阵批次,则 U、S 和 V 也会 以与input相同的批次维度进行批次处理。如果
some为 True(默认),该方法返回简化的奇异值分解。在这种情况下,如果input的最后两个维度是 m 和 n,那么返回的 U 和 V 矩阵将只包含 min(n, m) 个正交列。如果
compute_uv是 False,返回的 U 和 V 将是形状分别为 (m, m) 和 (n, n) 的零填充矩阵,并且与input在同一设备上。参数some在compute_uv为 False 时没有影响。支持浮点数、双精度、复数浮点数和复数双精度数据类型的输入。 U 和 V 的数据类型与
input的相同。S 将始终为实数,即使input是复数。警告
torch.svd()已被弃用,取而代之的是torch.linalg.svd()并将在未来的 PyTorch 版本中移除。U, S, V = torch.svd(A, some=some, compute_uv=True)(默认) 应替换为U, S, Vh = torch.linalg.svd(A, full_matrices=not some) V = Vh.mH
_, S, _ = torch.svd(A, some=some, compute_uv=False)应该替换为S = torch.linalg.svdvals(A)
注意
与
torch.linalg.svd()的区别:some是与torch.linalg.svd()的full_matrices相反的。请注意, 两者的默认值都是 True,因此默认行为实际上是相反的。torch.svd()返回 V,而torch.linalg.svd()返回 Vh,即 .如果
compute_uv为 False,torch.svd()返回零填充的张量给 U 和 Vh,而torch.linalg.svd()返回空张量。
注意
奇异值按降序返回。如果
input是矩阵的批次,则批次中每个矩阵的奇异值按降序返回。注意
The S tensor 只能在
compute_uv为 True 时用于计算梯度。注意
当
some为 False 时,在反向传播过程中,U[…, :, min(m, n):] 和 V[…, :, min(m, n):] 的梯度将被忽略,因为这些向量可以是相应子空间的任意基。注意
在CPU上,
torch.linalg.svd()的实现使用了LAPACK的例程?gesdd(一种分治算法)而不是?gesvd以提高速度。类似地,在GPU上,它在CUDA 10.1.243及更高版本上使用cuSOLVER的例程gesvdj和gesvdjBatched,在早期版本的CUDA上使用MAGMA的例程gesdd。注意
返回的 U 将不是连续的。矩阵(或矩阵批次)将表示为列优先矩阵(即 Fortran 连续)。
警告
关于U和V的梯度只有在输入没有零或重复的奇异值时才是有限的。
警告
如果任意两个奇异值之间的距离接近于零,那么相对于U和V的梯度在数值上将是不稳定的,因为它们依赖于 。当矩阵具有较小的奇异值时,同样的情况也会发生,因为这些梯度也依赖于S^{-1}。
警告
对于复数值的
input,奇异值分解不是唯一的, 因为 U 和 V 可以乘以任意相位因子 在每一列上。 当input具有重复的奇异值时,也会发生同样的情况,此时可以乘以旋转矩阵 来旋转 U 和 V 中跨越子空间的列,并且 生成的向量将跨越相同的子空间。 不同的平台,如 NumPy,或在不同设备类型上的输入, 可能会产生不同的 U 和 V 张量。- Parameters
- Keyword Arguments
输出 (元组, 可选) – 输出张量元组
示例:
>>> a = torch.randn(5, 3) >>> a tensor([[ 0.2364, -0.7752, 0.6372], [ 1.7201, 0.7394, -0.0504], [-0.3371, -1.0584, 0.5296], [ 0.3550, -0.4022, 1.5569], [ 0.2445, -0.0158, 1.1414]]) >>> u, s, v = torch.svd(a) >>> u tensor([[ 0.4027, 0.0287, 0.5434], [-0.1946, 0.8833, 0.3679], [ 0.4296, -0.2890, 0.5261], [ 0.6604, 0.2717, -0.2618], [ 0.4234, 0.2481, -0.4733]]) >>> s tensor([2.3289, 2.0315, 0.7806]) >>> v tensor([[-0.0199, 0.8766, 0.4809], [-0.5080, 0.4054, -0.7600], [ 0.8611, 0.2594, -0.4373]]) >>> torch.dist(a, torch.mm(torch.mm(u, torch.diag(s)), v.t())) tensor(8.6531e-07) >>> a_big = torch.randn(7, 5, 3) >>> u, s, v = torch.svd(a_big) >>> torch.dist(a_big, torch.matmul(torch.matmul(u, torch.diag_embed(s)), v.mT)) tensor(2.6503e-06)