Ash*_*ppa 4 c++ python numpy linear-algebra armadillo
在我的Python代码中,我使用numpy.linalg.svd计算一些数据的SVD :
from numpy import linalg
(_, _, v) = linalg.svd(m)
Run Code Online (Sandbox Code Playgroud)
由此返回的V矩阵是:
[[ 0.4512937 -0.81992002 -0.35222884]
[-0.22254721 0.27882908 -0.93419863]
[ 0.86417981 0.4999855 -0.05663711]]
Run Code Online (Sandbox Code Playgroud)
在将我的代码移植到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);
Run Code Online (Sandbox Code Playgroud)
相同数据的结果V是:
0.4513 -0.2225 -0.8642
-0.8199 0.2788 -0.5000
-0.3522 -0.9342 0.0566
Run Code Online (Sandbox Code Playgroud)
我们可以看到,来自犰狳的V的转置与来自NumPy的V匹配.除此之外,对于来自犰狳的V的最后一列.这些值与NumPy结果的最后一行中的值具有相反的符号.
这里发生了什么?为什么两个流行的库的SVD结果不同?哪两个是正确的结果?
两者都是正确的... v你从numpy得到的行是特征向量M.dot(M.T)(转置将是复杂情况下的共轭转置).特征向量在一般情况下仅定义为乘法常数,因此您可以将任意行乘以v不同的数字,它仍然是特征向量矩阵.
还有一个额外的约束,v即它是一个酉矩阵,它松散地转换为正交的行.这会将每个特征向量的可用选择减少到仅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
Run Code Online (Sandbox Code Playgroud)
实际上,你只能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
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2066 次 |
| 最近记录: |