Python scikit学习PCA:矩阵变换产生带翻转符号的PC估计

Python scikit学习PCA:矩阵变换产生带翻转符号的PC估计,python,scikit-learn,pca,Python,Scikit Learn,Pca,我正在使用scikit学习在上执行PCA。scikit学习文档 由于奇异值分解的实现细节 (SVD),在该实现中使用,在 同一矩阵可能导致符号翻转的主成分 (改变方向)。因此,始终使用 同一个估计器反对以一致的方式转换数据 问题是,我不认为我在使用不同的估计器对象,但当与SAS的PROC PRINCOMP过程中的结果进行比较时,我的一些PC的符号发生了翻转 对于数据集中的第一次观察,SAS PC为: PC1 PC2 PC3 PC4 PC5 2.0508

我正在使用scikit学习在上执行PCA。scikit学习文档

由于奇异值分解的实现细节 (SVD),在该实现中使用,在 同一矩阵可能导致符号翻转的主成分 (改变方向)。因此,始终使用 同一个估计器反对以一致的方式转换数据

问题是,我不认为我在使用不同的估计器对象,但当与SAS的
PROC PRINCOMP
过程中的结果进行比较时,我的一些PC的符号发生了翻转

对于数据集中的第一次观察,SAS PC为:

PC1      PC2      PC3       PC4      PC5
2.0508   1.9600   -0.1663   0.2965   -0.0121
从scikit learn中,我得到了以下几点(在数量上非常接近):

以下是我正在做的:

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\u transform()
,但结果相同


我在这里做错了什么,我让电脑上的标志被翻转了?

你没有做错什么

文档提醒您的是,重复调用
fit
可能会产生不同的主成分,而不是它们与另一个PCA实现的关系

在所有组件上使用翻转符号不会导致结果错误-只要满足定义,结果就是正确的(每个组件的选择都会捕获数据中的最大差异量)。就目前而言,你得到的投影似乎只是镜像——它仍然满足定义,因此是正确的


如果在正确性之下,您担心实现之间的一致性,那么您可以在必要时将组件乘以-1。

SVD分解不能保证唯一-只有值是相同的,因为SVD()的不同实现可能会产生不同的符号。任何一个特征向量都可能有翻转的符号,并且在转换时会产生相同的结果,然后再转换回原始空间。sklearn中使用SVD分解的大多数算法都使用函数sklearn.utils.extmath.SVD_flip()来纠正这一点,并在算法之间强制执行相同的约定。出于历史原因,PCA()从未得到过此修复(尽管它可能应该…)

一般来说,这不需要担心,只是SVD算法的一个局限性


另一方面,我发现重视PC权重(以及通常的参数权重)是危险的,因为正是这些问题。数字/实现细节不应影响您的分析结果,但很多时候很难判断数据的结果是什么,以及您用于探索的算法的结果是什么。我知道这是一个家庭作业,不是一个选择,但重要的是要记住这些事情

回答这个问题可能更好:我之所以把它贴在这里而不是那里,是因为它似乎比统计数据更具体地针对scikit学习实现(以及我如何使用它)。事实上,SVD中没有符号(特征向量的加性逆就是特征向量),它们是通过实现而不是通过定义存在的。因此,PC的符号也未定义。@既然如此,在执行PC回归时,如何协调SAS和Python之间的结果?回归系数的参数估计也有不同的符号。我明白如果你只是做变量缩减,这没什么大不了的。它们似乎不会一直被翻转。PC 1、2和4翻转,但3和5不翻转。就其本身而言,我并不真正担心一致性。我只是想用Python复制一些SAS作业,并且担心不同的符号。硬件中的下一步是执行主成分回归(b/c数据集具有显著的多重共线性),我担心翻转的符号会导致不同的结果。@Clay我绝对不是统计专家,但在我看来(在主成分回归中)使用PC特征向量将回归系数转换回原始空间,结果应该是相同的,只要对PCA和regressionOk使用相同的转换,感谢反馈。我将继续比较PCR结果。PCR结果在参数估计上出现了翻转。不确定如何将其与SAS输出相协调。
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]])