我正在使用scikit-learn在this dataset上执行PCA。 scikit-learn文档states that
由于奇异值分解的实现微妙 (SVD),在这个实现中使用,运行适合两次 相同的矩阵可以导致主要组件翻转标志 (改变方向)。因此,始终使用非常重要 相同的估算器对象以一致的方式转换数据。
问题是我不认为我使用不同的估算器对象,但与SAS PROC PRINCOMP
程序的结果相比,我的某些PC的迹象被翻转。
对于数据集中的第一次观察,SAS PC是:
PC1 PC2 PC3 PC4 PC5
2.0508 1.9600 -0.1663 0.2965 -0.0121
从scikit-learn,我得到以下(其数量非常接近):
PC1 PC2 PC3 PC4 PC5
-2.0536 -1.9627 -0.1666 -0.297 -0.0122
这就是我正在做的事情:
import pandas as pd
import numpy as np
from sklearn.decomposition.pca import PCA
sourcef = pd.read_csv('C:/mydata.csv')
frame = pd.DataFrame(sourcef)
# Some pandas evals, regressions, etc... that I'm not showing
# but not affecting the matrix
# Make sure we are working with the proper data -- drop the response variable
cols = [col for col in frame.columns if col not in ['response']]
# Separate out the data matrix from the response variable vector
# into numpy arrays
frame2_X = frame[cols].values
frame2_y = frame['response'].values
# Standardize the values
X_means = np.mean(frame2_X,axis=0)
X_stds = np.std(frame2_X,axis=0)
y_mean = np.mean(frame2_y)
y_std = np.std(frame2_y)
frame2_X_stdz = np.copy(frame2_X)
frame2_y_stdz = frame2_y.astype(numpy.float32, copy=True)
for (x,y), value in np.ndenumerate(frame2_X_stdz):
frame2_X_stdz[x][y] = (value - X_means[y])/X_stds[y]
for index, value in enumerate(frame2_y_stdz):
frame2_y_stdz[index] = (float(value) - y_mean)/y_std
# Show the first 5 elements of the standardized values, to verify
print frame2_X_stdz[:,0][:5]
# Show the first 5 lines from the standardized response vector, to verify
print frame2_y_stdz[:5]
那些退房确定:
[ 0.9508 -0.5847 -0.2797 -0.4039 -0.598 ]
[ 1.0726 -0.5009 -0.0942 -0.1187 -0.8043]
继续......
# Create a PCA object
pca = PCA()
pca.fit(frame2_X_stdz)
# Create the matrix of PC estimates
pca.transform(frame2_X_stdz)
这是最后一步的输出:
Out[16]: array([[-2.0536, -1.9627, -0.1666, -0.297 , -0.0122],
[ 1.382 , -0.382 , -0.5692, -0.0257, -0.0509],
[ 0.4342, 0.611 , 0.2701, 0.062 , -0.011 ],
...,
[ 0.0422, 0.7251, -0.1926, 0.0089, 0.0005],
[ 1.4502, -0.7115, -0.0733, 0.0013, -0.0557],
[ 0.258 , 0.3684, 0.1873, 0.0403, 0.0042]])
我已经尝试将pca.fit()
和pca.transform()
替换为pca.fit_transform()
,但我的结果却相同。
我在这里犯了什么错误,我正在拿着标牌翻转的电脑?
答案 0 :(得分:5)
你没有做错任何事。
文档警告你的是,对fit
的重复调用可能产生不同的主要组件 - 而不是它们与另一个PCA实现的关系。
在所有组件上都有翻转符号不会使结果错误 - 只要符合定义,结果就是正确的(选择每个组件以便捕获最大差异量)在数据中)。就目前而言,您所获得的投影似乎只是镜像 - 它仍然符合定义,因此是正确的。
如果在正确性之下,你担心实现之间的一致性,你可以在必要时简单地将组件乘以-1。
答案 1 :(得分:0)
不保证SVD分解是唯一的 - 只有值是相同的,因为svd()的不同实现可以产生不同的符号。任何特征向量都可以有翻转符号,并且在转换时会产生相同的结果,然后转换回原始空间。 sklearn中使用SVD分解的大多数算法使用函数sklearn.utils.extmath.svd_flip()来纠正这个问题,并在算法之间强制执行相同的约定。由于历史原因,PCA()从来没有得到过这个修复(尽管它应该......)
一般来说,这不是一件值得担心的事情 - 只是通常实施的SVD算法的限制。
另外需要注意的是,我发现将PC权重(以及一般参数权重)的重要性分配给了危险,因为这些问题正好存在。数值/实现细节不应该影响您的分析结果,但很多时候很难说出数据的结果是什么,以及您用于探索的算法的结果是什么。我知道这是一项家庭作业,不是一种选择,但重要的是记住这些事情!