torch.svd
- torch.svd(input, some=True, compute_uv=True, *, out=None)
-
计算输入矩阵或矩阵批次的奇异值分解。 奇异值分解表示为元组(U, S, V),使得
input
$= U \text{diag}(S) V^{\text{H}}$。 其中$V^{\text{H}}$对于实数输入是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
不起作用。支持
input
为float、double、cfloat和cdouble的数据类型的输入。U和V的数据类型与input
相同,而S始终是实数值,即使input
是复数类型。警告
torch.svd()
已被弃用,并将在未来的 PyTorch 版本中移除,请使用torch.linalg.svd()
。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(即 $V^{\text{H}}$)。 -
如果
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):] 的梯度,因为这些向量可以是相应子空间的任意基。注意
torch.linalg.svd()
在 CPU 上的实现使用 LAPACK 的 ?gesdd 方法(一种分治算法)来提高速度,而不是使用 ?gesvd。类似地,在 GPU 上,它在 CUDA 10.1.243 及更高版本中使用 cuSOLVER 的 gesvdj 和 gesvdjBatched 方法,并在早期版本的 CUDA 中使用 MAGMA 的 gesdd 方法。注意
返回的 U 将不会是连续的。矩阵(或矩阵批)将以列为主顺序的形式表示(即 Fortran 连续性)。
警告
只有当输入没有零或重复的奇异值时,U 和 V 的梯度才有有限值。
警告
如果任意两个奇异值之间的距离接近于零,U 和 V 的梯度将变得数值上不稳定,因为它们依赖于$\frac{1}{\min_{i \neq j} \sigma_i^2 - \sigma_j^2}$。当矩阵包含很小的奇异值时,也会出现同样的问题,因为这些梯度还取决于S^{-1}。
警告
对于复数值的
input
,奇异值分解不是唯一的,因为U和V的每一列可以乘以任意相位因子$e^{i \phi}$。当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)
-