用numpy的eigh和svd计算的特征向量不匹配 [英] Eigenvectors computed with numpy's eigh and svd do not match
问题描述
考虑奇异值分解M = USV *.然后,M * M的特征值分解给出M * M = V(S * S)V * = VS * U * USV *.我希望通过numpy验证这种相等性,方法是显示eigh
函数返回的特征向量与svd
函数返回的特征向量相同:
Consider singular value decomposition M=USV*. Then the eigenvalue decomposition of M* M gives M* M= V (S* S) V*=VS* U* USV*. I wish to verify this equality with numpy by showing that the eigenvectors returned by eigh
function are the same as those returned by svd
function:
import numpy as np
np.random.seed(42)
# create mean centered data
A=np.random.randn(50,20)
M= A-np.array(A.mean(0),ndmin=2)
# svd
U1,S1,V1=np.linalg.svd(M)
S1=np.square(S1)
V1=V1.T
# eig
S2,V2=np.linalg.eigh(np.dot(M.T,M))
indx=np.argsort(S2)[::-1]
S2=S2[indx]
V2=V2[:,indx]
# both Vs are in orthonormal form
assert np.all(np.isclose(np.linalg.norm(V1,axis=1), np.ones(V1.shape[0])))
assert np.all(np.isclose(np.linalg.norm(V1,axis=0), np.ones(V1.shape[1])))
assert np.all(np.isclose(np.linalg.norm(V2,axis=1), np.ones(V2.shape[0])))
assert np.all(np.isclose(np.linalg.norm(V2,axis=0), np.ones(V2.shape[1])))
assert np.all(np.isclose(S1,S2))
assert np.all(np.isclose(V1,V2))
最后一个断言失败.为什么?
The last assertion fails. Why?
推荐答案
只需玩少量数字即可调试问题.
Just play with small numbers to debug your problem.
以A=np.random.randn(3,2)
开头,而不是尺寸为(50,20)
Start with A=np.random.randn(3,2)
instead of your much larger matrix with size (50,20)
在我的随机情况下,我发现
In my random case, I find that
v1 = array([[-0.33872745, 0.94088454],
[-0.94088454, -0.33872745]])
以及v2
:
v2 = array([[ 0.33872745, -0.94088454],
[ 0.94088454, 0.33872745]])
它们仅在符号上有所不同,显然,即使标准化为具有单位模块,矢量在符号上也可能不同.
they only differ for a sign, and obviously, even if normalized to have unit module, the vector can differ for a sign.
现在,如果您尝试把戏
assert np.all(np.isclose(V1,-1*V2))
对于您原来的大矩阵,它失败了……再次,这没关系.发生的情况是,某些向量已与-1
相乘,而另一些则没有.
for your original big matrix, it fails... again, this is OK. What happens is that some vectors have been multiplied by -1
, some others haven't.
检查向量之间是否相等的正确方法是:
A correct way to check for equality between the vectors is:
assert allclose(abs((V1*V2).sum(0)),1.)
实际上,要了解其工作原理,可以打印以下数量:
and indeed, to get a feeling of how this works you can print this quantity:
(V1*V2).sum(0)
根据向量,确实是+1
或-1
:
array([ 1., -1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., -1., 1., 1., 1., -1., -1.])
在大多数情况下,尤其是从随机矩阵开始时,会发生这种情况.但是请注意,如@Sven Marnach在下面的评论中指出的那样,如果一个或多个特征值的特征空间的维数大于1
,则该测试可能会失败.
This will happen in most cases, especially if starting from a random matrix. Notice however that this test will likely fail if one or more eigenvalues has an eigenspace of dimension larger than 1
, as pointed out by @Sven Marnach in his comment below:
除了向量乘以-1之外,可能还有其他差异. 如果任何特征值具有多维特征空间,则您 可能会获得该特征空间的任意正交基础,并且 这样的基地可以通过套期交易彼此相对旋转 一元矩阵
There might be other differences than just vectors multiplied by -1. If any of the eigenvalues has a multi-dimensional eigenspace, you might get an arbitrary orthonormal basis of that eigenspace, and to such bases might be rotated against each other by an arbitraty unitarian matrix
这篇关于用numpy的eigh和svd计算的特征向量不匹配的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!