快捷键

torch.linalg.svd

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

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

K\mathbb{K}R\mathbb{R}C\mathbb{C} ,当 k = min(m,n)时,矩阵 AKm×nA \in \mathbb{K}^{m \times n} 的满秩奇异值分解(SVD)定义为

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

其中,当 VV 为复数时, diag(S)Km×n\operatorname{diag}(S) \in \mathbb{K}^{m \times n}VHV^{\text{H}} 是共轭转置,当 VV 为实数时,是转置。在实数情况下,矩阵 UUVV (以及 VHV^{\text{H}} )是正交的,在复数情况下是酉的。

当 m > n(或 m < n)时,我们可以去掉 U(或 V)的最后一个 m - n(或 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 数据类型。也支持矩阵批处理,如果 A 是矩阵批,则输出具有相同的批维度。

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

奇异值按降序返回。

参数 full_matrices 在完整(默认)和简化 SVD 之间进行选择。

CUDA 中使用 cuSOLVER 后端时,可以通过 driver kwarg 来选择用于计算 SVD 的算法。驱动程序的选择是精度和速度之间的权衡。

  • 如果 A 是良态的(其条件数不是太大),或者你不在乎一些精度损失。

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

    • 如果 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 也不连续。由于这种非唯一性,不同的硬件和软件可能计算不同的奇异向量。

这种非唯一性是由以下事实引起的:在实数情况下,将任意一对单向量 uk,vku_k, v_k 乘以-1,或在复数情况下乘以 eiϕ,ϕRe^{i \phi}, \phi \in \mathbb{R} ,会产生矩阵的另一对有效单向量。因此,损失函数不应依赖于这个 eiϕe^{i \phi} 量,因为它没有明确定义。当计算该函数的梯度时,会检查复数输入。因此,当输入是复数且位于 CUDA 设备上时,该函数梯度的计算将同步该设备与 CPU。

警告

使用 U 或 Vh 计算的梯度只有在 A 没有重复的单值时才是有限的。如果 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.eigh() 用于计算厄米矩阵和对称矩阵的特征值分解的(更快)函数。

torch.linalg.qr() 用于另一种(更快)的分解,适用于一般矩阵。

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

  • full_matrices (布尔值,可选) – 控制是否计算全 SVD 或降阶 SVD,从而确定返回的张量 U 和 Vh 的形状。默认:True。

关键字参数:
  • driver (字符串,可选) – 要使用的 cuSOLVER 方法的名称。此关键字参数仅在 CUDA 输入上有效。可用选项有:None,gesvd,gesvdj 和 gesvda。默认:None。

  • out (元组,可选) – 三个张量的输出元组。如果为 None,则忽略。

返回值:

与上面提到的 UUSSVHV^{\text{H}} 对应的命名元组 (U, S, Vh)。

即使 A 是复数,S 也始终是实值。它也将按降序排列。

U 和 Vh 将具有与 A 相同的数据类型。左/右奇异向量将由 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 贡献者。

使用 Sphinx 构建,并使用 Read the Docs 提供的主题。

文档

PyTorch 的全面开发者文档

查看文档

教程

深入了解初学者和高级开发者的教程

查看教程

资源

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

查看资源