【问题标题】:Why does SVD result of Armadillo differ from NumPy?为什么犰狳的 SVD 结果与 NumPy 不同?
【发布时间】:2013-11-21 04:28:27
【问题描述】:

在我的 Python 代码中,我正在使用 numpy.linalg.svd 计算一些数据的 SVD:

from numpy import linalg
(_, _, v) = linalg.svd(m)

由此返回的V矩阵为:

[[ 0.4512937  -0.81992002 -0.35222884]
 [-0.22254721  0.27882908 -0.93419863]
 [ 0.86417981  0.4999855  -0.05663711]]

在将我的代码移植到 C++ 时,我转而使用 Armadillo 来计算 SVD:

#include <armadillo>

arma::fmat M; // Input data
arma::fmat U;
arma::fvec S;
arma::fmat V;
arma::svd(U, S, V, M);

相同数据的结果 V 是:

  0.4513  -0.2225  -0.8642
 -0.8199   0.2788  -0.5000
 -0.3522  -0.9342   0.0566

我们可以看到来自 Armadillo 的 V 的转置与来自 NumPy 的 V 相匹配。除此之外,对于犰狳的 V 的最后一列。这些值与 NumPy 结果最后一行中的值符号相反。

这里发生了什么?为什么两个流行库的 SVD 结果如此不同?两者中哪一个是正确的结果?

【问题讨论】:

  • 您应用 SVD 的原始矩阵是什么?你能保证它在两个系统之间是相同的吗?通常唯一的区别可能是特征向量的比例......
  • @AlexanderL.Belikoff:是的,输入数据是相同的。在 C++ 中,类型是浮点数,而在 Python 中,我猜是双精度数。但是,这种精度差异应该无关紧要吗?
  • 从技术上讲,SVD 分解不是唯一的(不确定符号的变化)。除此之外,可能两者之一是返回 V* 而不是 V,因此是转置。此外,在实数方阵的 SVD 中,会产生一个 U 和一个 V,它们都是旋转矩阵,armadillo 是正确的。你能发布你的原始矩阵吗?
  • @sbabbi:输入矩阵不是正方形的。在此分享:pastebin.com/bPgKER7E
  • 犰狳返回V,而numpy返回V*。至于符号的变化,我不知道,但可能两个结果都是正确的,V 中的符号变化被U 中的另一个平衡。您可以计算 USV 并检查它是否等于原始矩阵。

标签: c++ python numpy linear-algebra armadillo


【解决方案1】:

两者都是正确的...您从 numpy 获得的 v 的行是 M.dot(M.T) 的特征向量(在复杂情况下,转置将是共轭转置)。特征向量在一般情况下仅定义为乘法常数,因此您可以将v 的任何行乘以不同的数字,它仍然是特征向量矩阵。

v 有一个额外的约束,即它是一个 unitary matrix,它松散地转换为它的行是正交的。这会将每个特征向量的可用选择减少到只有 2 个:指向任一方向的归一化特征向量。但是您仍然可以将任何行乘以 -1 并且仍然有一个有效的v

如果您想为您的矩阵测试它,我已将其加载为a

>>> u, d, v = np.linalg.svd(a)
>>> D = np.zeros_like(a)
>>> idx = np.arange(a.shape[1])
>>> D[idx, idx] = d
>>> np.allclose(a, u.dot(D).dot(v))
True
>>> v[2] *= -1
>>> np.allclose(a, u.dot(D).dot(v))
True

实际上,在实数域中你只能将v的行乘以-1,但在复杂情况下你可以将它们乘以绝对值1的任意复数:

>>> vv = v.astype(np.complex)
>>> vv[0] *= (1+1.j)/np.sqrt(2)
>>> np.allclose(a, u.dot(D).dot(v))
True

【讨论】:

  • 谢谢杰米!我正在使用 v 来旋转点,就像在 PCA 中一样。所以,我想用我从犰狳那里得到的 V 没有什么坏处?
  • 是的,轴的对齐方式不会改变,唯一的区别是orientation of your basis,在大多数情况下这不应该是一个相关问题。请注意,至少在这种情况下,numpy 给出了基础的通常右手方向。同样,我认为差异与对齐数据无关。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-07
  • 2021-07-21
  • 2011-08-21
相关资源
最近更新 更多