我正试图跟随Abdi&Williams(2010年),使用SVD构建主要组件。
当我显示带有sklearn的拟合PCA的Principal Component Analysis属性时,它们的大小与我手动计算的大小完全相同,但有些(不是全部)符号相反。是什么引起的?
更新:下面我的(部分)答案包含一些附加信息。
以下面的示例数据为例:
from pandas_datareader.data import DataReader as dr
import numpy as np
from sklearn.decomposition import PCA
from sklearn.preprocessing import scale
# sample data - shape (20, 3), each column standardized to N~(0,1)
rates = scale(dr(['DGS5', 'DGS10', 'DGS30'], 'fred',
start='2017-01-01', end='2017-02-01').pct_change().dropna())
# with sklearn PCA:
pca = PCA().fit(rates)
print(pca.components_)
[[-0.58365629 -0.58614003 -0.56194768]
[-0.43328092 -0.36048659 0.82602486]
[-0.68674084 0.72559581 -0.04356302]]
# compare to the manual method via SVD:
u, s, Vh = np.linalg.svd(np.asmatrix(rates), full_matrices=False)
print(Vh)
[[ 0.58365629 0.58614003 0.56194768]
[ 0.43328092 0.36048659 -0.82602486]
[-0.68674084 0.72559581 -0.04356302]]
# odd: some, but not all signs reversed
print(np.isclose(Vh, -1 * pca.components_))
[[ True True True]
[ True True True]
[False False False]]
最佳答案
正如您在回答中所指出的,奇异值分解(SVD)的结果在奇异向量方面不是唯一的。事实上,如果x的svd是\sum_1^r\s_i u i v_i^ \top:
使用降序排序的s_i,您可以看到您可以更改u_1和v_1的符号(即“翻转”),减号将取消,因此公式仍将保持不变。
这表明SVD是唯一的,直到符号对的左奇异向量和右奇异向量发生变化。
由于PCA只是x的SVD(或x^\top x的特征值分解),因此不能保证每次执行相同x时,它不会返回不同的结果。可以理解,Scikit Learn实现希望避免这种情况:它们通过强制(任意)绝对值中最大的u-i系数为正,来保证返回(存储在u和v中)的左右奇异向量始终相同。
如您所见,读数为:首先,他们用linalg.svd()
计算u和v。然后,对于每个向量u-i(即u行),如果它的绝对值中的最大元素是正数,它们就不做任何事情。否则,它们会将u-i更改为-u-i,相应的左奇异向量v-i更改为-v-i。如前所述,这不会更改SVD公式,因为减号取消。但是,现在可以保证处理后返回的U和V始终相同,因为符号上的不确定性已被移除。
关于python - 在sklearn.decomposition.PCA中,为什么components_为负?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/44765682/