torch.svd#
- torch.svd(input, some=True, compute_uv=True, *, out=None)#
计算输入
input
的矩阵或矩阵批的奇异值分解。奇异值分解表示为命名元组 (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 时不起作用。支持
input
的 float、double、cfloat 和 cdouble 数据类型。U 和 V 的 dtypes 与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
是一个矩阵批次,则批次中每个矩阵的奇异值都会以降序排列。注意
只有当
compute_uv
为 True 时,S 张量才能用于计算梯度。注意
当
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 张量。- 参数
- 关键字参数
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)