【问题标题】:Why is my SVD calculation different than numpy's SVD calculation of this matrix?为什么我的 SVD 计算与 numpy 对该矩阵的 SVD 计算不同?
【发布时间】:2018-09-24 19:53:17
【问题描述】:

我正在尝试手动计算下面定义的矩阵 A 的 SVD,但我遇到了一些问题。手动计算它并使用 numpy 中的 svd 方法产生两个不同的结果。

以下手动计算:

import numpy as np
A = np.array([[3,2,2], [2,3,-2]])
V = np.linalg.eig(A.T @ A)[1]
U = np.linalg.eig(A @ A.T)[1]
S = np.c_[np.diag(np.sqrt(np.linalg.eig(A @ A.T)[0])), [0,0]]
print(A)
print(U @ S @ V.T)

并通过 numpy 的 svd 方法计算:

X,Y,Z = np.linalg.svd(A)
Y = np.c_[np.diag(Y), [0,0]]
print(A)
print(X @ Y @ Z)

当这两个代码运行时。手动计算不等于 svd 方法。为什么这两个计算之间存在差异?

【问题讨论】:

  • 嗯,我逐个元素地分解问题,发现如果你只比较XU = np.linalg.eig(A @ A.T)[1],你不会得到相同的矩阵(符号有些不同)。即使ZV 在Z 的第二排与V 的第三排相似的意义上也不同,反之亦然,有些符号相反。似乎 numpy linalg 可能存在一些问题。检查第二个答案here
  • 我看到行和/或符号被切换,但我不明白这是为什么。 U @ S @ V.T 也不等于 A,我也不明白。
  • 答案是 U 和 V 一开始就没有正确计算。为此,只需取一个 2,2 矩阵并使用一些在线工具计算 A,然后比较 linalg 的 eig 是否给您相同的答案。如果没有,那就有问题了

标签: python numpy svd


【解决方案1】:

查看np.linalg.eig(A.T @ A)返回的特征值:

In [57]: evals, evecs = np.linalg.eig(A.T @ A)

In [58]: evals
Out[58]: array([2.50000000e+01, 3.61082692e-15, 9.00000000e+00])

所以(忽略正常的浮点不精度),它计算出 [25, 0, 9]。与这些特征值关联的特征向量在evecs 的列中,顺序相同。但是您对S 的构造与该顺序不匹配;这是你的S

In [60]: S
Out[60]: 
array([[5., 0., 0.],
       [0., 3., 0.]])

当您计算 U @ S @ V.T 时,S @ V.T 中的值未正确对齐。

作为一种快速修复,您可以重新运行您的代码并明确设置S,如下所示:

S = np.array([[5, 0, 0],
              [0, 0, 3]])

通过该更改,您的代码输出

[[ 3  2  2]
 [ 2  3 -2]]
[[-3. -2. -2.]
 [-2. -3.  2.]]

这样更好,但为什么符号是错误的?现在的问题是您已经独立计算了UV。特征向量不是唯一的;它们是本征空间的基础,而这样的基础并不是唯一的。如果特征值很简单,并且向量被归一化为长度为 1(numpy.linalg.eig 确实如此),则仍然需要选择符号。也就是说,如果v 是一个特征向量,那么-v 也是。 eig 在计算 UV 时所做的选择不一定会导致在计算 U @ S @ V.T 时恢复 A 的符号。

事实证明,只需将UV 中的所有符号颠倒过来,即可得到您期望的结果。这是您的脚本的修改版本,可生成您预期的输出:

import numpy as np

A = np.array([[3,  2,  2],
              [2,  3, -2]])

U = np.linalg.eig(A @ A.T)[1]
V = -np.linalg.eig(A.T @ A)[1]
#S = np.c_[np.diag(np.sqrt(np.linalg.eig(A @ A.T)[0])), [0,0]]
S = np.array([[5, 0, 0],
              [0, 0, 3]])

print(A)
print(U @ S @ V.T)

输出:

[[ 3  2  2]
 [ 2  3 -2]]
[[ 3.  2.  2.]
 [ 2.  3. -2.]]

【讨论】:

  • 但是对于 SVD,S 矩阵不是必须具有沿对角线降序排列的奇异值吗?
  • 否,但必须构造 SVD 中的矩阵,以便奇异值和相应的奇异向量正确对齐。 numpy.linalg.svd 按降序返回奇异值这一事实是实现细节,而不是数学要求。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-10
  • 1970-01-01
相关资源
最近更新 更多