其他分享
首页 > 其他分享> > c – 为什么犰狳的SVD结果与NumPy不同?

c – 为什么犰狳的SVD结果与NumPy不同?

作者:互联网

在我的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

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

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

解决方法:

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

对v的附加约束是unitary matrix,它松散地转换为正交的行.这会将每个特征向量的可用选择减少到仅2:指向任一方向的归一化特征向量.但你仍然可以将任意行乘以-1并仍然有一个有效的v.

如果你想测试它的矩阵,我已经加载为:

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

标签:python,c-2,numpy,linear-algebra,armadillo
来源: https://codeday.me/bug/20190529/1175952.html