2 个协方差矩阵仅右上角和左下角的值不同。然而,主成分特征向量(右列)的符号已翻转。
import numpy as np
cov = np.array([[9369, 7060, 16469],
[7060, 8127, 23034],
[16469, 23034, 126402]])
eigenvalues, eigenvectors = np.linalg.eigh(cov)
print('Cov 1')
print(eigenvalues)
print(eigenvectors)
cov2 = np.array([[9369, 7060, *18969*],
[7060, 8127, 23034],
[*18969*, 23034, 126402]])
eigenvalues, eigenvectors = np.linalg.eigh(cov2)
print('Cov 2')
print(eigenvalues)
print(eigenvectors)
结果:
Cov 1
[ 1188.72951707 9507.3058357 133201.96464723]
[[-0.5549483 0.82002403 0.13997491]
[ 0.8280924 0.52849364 0.18696912]
[-0.07934332 -0.21967035 0.97234231]]
Cov 2
[ 1390.92828009 8581.02234156 133926.04937835]
[[-0.57175381 0.80502124 -0.15823521]
[ 0.817929 0.54427789 -0.18642352]
[-0.06395096 -0.23601353 -0.96964318]]
我怎样才能防止这种情况发生,或者以某种方式“纠正”,以便符号相同 - 在两种情况下都是正数或负数?
最后,我认为唯一可靠(但不是那么优雅)的解决方案是编写一个函数来手动进行检查(这里,我强制矩阵中的每个向量的第一个坐标为正。如果它为空,我检查第二个,依此类推。):
def adjust_eigenvectors(eigenvectors : np.ndarray):
n,m = eigenvectors.shape
for i in range(m):
for j in range(n):
if eigenvectors[j, i] > 0:
break
elif eigenvectors[j, i] < 0:
eigenvectors[:, i] = -eigenvectors[:, i]
break
return eigenvectors
eigenvalues, eigenvectors = np.linalg.eigh(cov2)
print('Cov 2')
print(eigenvalues)
print(adjust_eigenvectors(eigenvectors))
请注意,此函数会就地执行此操作并返回值,因此从技术上讲,无需编写
return eigenvectors
,因为它已经被修改了。
我不太喜欢这个解决方案,因为它不是矢量化的(更不用说 numpy 风格的),但它修复了解决方案。