评价此页

torch.svd#

torch.svd(input, some=True, compute_uv=True, *, out=None)#

计算矩阵或一批矩阵 input 的奇异值分解。奇异值分解表示为一个命名元组 (U, S, V),使得 input =Udiag(S)VH= U \text{diag}(S) V^{\text{H}}。其中 VHV^{\text{H}} 对于实数输入是 V 的转置,对于复数输入是 V 的共轭转置。如果 input 是一批矩阵,那么 USV 也将以与 input 相同的批处理维度进行批处理。

如果 someTrue(默认值),该方法返回简化奇异值分解。在这种情况下,如果 input 的最后两个维度是 mn,则返回的 UV 矩阵将只包含 min(n, m) 个正交列。

如果 compute_uvFalse,返回的 UV 将分别是形状为 (m, m)(n, n) 的零填充矩阵,且与 input 位于相同的设备上。当 compute_uvFalse 时,参数 some 不起作用。

支持 float、double、cfloat 和 cdouble 数据类型的 input。`U` 和 `V` 的数据类型与 input 相同。即使 input 是复数,`S` 也将始终是实数值。

警告

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() 的区别

注意

奇异值按降序返回。如果 input 是一批矩阵,则批中每个矩阵的奇异值都按降序返回。

注意

只有当 compute_uvTrue 时,才能使用 S 张量计算梯度。

注意

someFalse 时,反向传播时将忽略 `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 连续存储)。

警告

只有当输入没有零奇异值或重复奇异值时,关于 UV 的梯度才是有穷的。

警告

如果任意两个奇异值之间的距离接近零,关于 UV 的梯度将是数值不稳定的,因为它们依赖于 1minijσi2σj2\frac{1}{\min_{i \neq j} \sigma_i^2 - \sigma_j^2}。当矩阵具有较小的奇异值时也会发生同样的情况,因为这些梯度也依赖于 S^{-1}

警告

对于复数值 input,奇异值分解不是唯一的,因为 UV 的每一列都可以乘以任意的相位因子 eiϕe^{i \phi}。当 input 具有重复奇异值时也会发生同样的情况,此时可以将 UV 中张成子空间的列乘以一个旋转矩阵,并且 得到的向量将张成相同的子空间。不同的平台(如 NumPy)或不同设备类型的输入,可能会产生不同的 UV 张量。

参数:
  • input (张量) – 大小为 (*, m, n) 的输入张量,其中 * 是由 (m, n) 矩阵组成的一个或多个批处理维度。

  • some (布尔值, 可选) – 控制是计算简化分解还是完整分解,从而影响返回的 UV 的形状。默认值:True

  • compute_uv (布尔值, 可选) – 控制是否计算 UV。默认值:True

关键字参数:

out (元组, 可选) – 输出张量元组

示例

>>> 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)