2014-01-14 16 views
4

我使用scikit-learn在this dataset上執行PCA。該scikit學習文檔states thatscikit-learn PCA:矩陣轉換產生帶翻轉符號的PC估計值

由於奇異值分解 (SVD),這是在這個實現中使用的執行微妙之處,在 同一矩陣轉動配合兩次會導致主成分與標誌翻轉 (改變方向)。出於這個原因,始終使用相同的估計對象以一致的方式轉換數據非常重要。

的問題是,我不認爲我使用的是不同的估計的對象,但我的一些個人電腦的標誌翻轉,而在SAS的PROC PRINCOMP過程結果的時候。

對於數據集中的第一個觀察,SAS PC是:

PC1  PC2  PC3  PC4  PC5 
2.0508 1.9600 -0.1663 0.2965 -0.0121 

從scikit學習,我得到以下(這是在幅度非常接近):

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()嘗試過,但我結束達到相同的結果。

我在做什麼錯在這裏,我得到的電腦符號翻轉?

+2

這可能上更好的回答:http://stats.stackexchange.com/ –

+1

我張貼在這裏的原因,而不是有因爲它似乎更具體的scikit學習執行(我怎麼使用它)比統計數字。 – Clay

+0

恕我直言,這是數學,而不是統計。事實上,SVD(特徵向量的加法逆是一個特徵向量)沒有跡象,它們通過實現而不是定義。因此,PC的標誌也是未定義的。 – alko

回答

5

你沒有做錯什麼。

文檔警告你的是,重複調用fit可能會產生不同的主要組件,而不是它們與另一個PCA實現的關係。

具有上的所有組件翻轉標誌不會使結果 - 結果是,只要權,因爲它滿足了定義(各組分被選擇爲使得它捕獲在數據方差的最大量) 。就目前而言,您所看到的投影似乎只是鏡像 - 它仍然符合定義,因此是正確的。

如果在正確性之下,您擔心實現之間的一致性,您可以在需要時將組件乘以-1。

+0

他們似乎並沒有持續翻轉。 PC 1,2和4翻轉,但不是3和5.我本身並不擔心一致性。我只是試圖在Python中複製一些SAS作業,並擔心不同的跡象。 HW中的下一步是執行主成分迴歸(b/c數據集具有顯着的多重共線性),我擔心翻轉的跡象會導致不同的結果。 – Clay

+0

@Clay我絕不是統計專家,但在我看來,由於(在主成分迴歸)迴歸係數變換**使用PC的特徵向量回**到原來的空間,其結果應是一樣的,只要你對PCA和迴歸使用相同的變換 – goncalopp

+0

好的,謝謝你的反饋。我將繼續並比較PCR結果。 – Clay

0

不保證SVD分解是唯一的 - 只有值會相同,因爲svd()的不同實現可以產生不同的符號。任何特徵向量都可以有翻轉的符號,並且在轉換時會產生相同的結果,然後轉換回原始空間。在sklearn大多數算法,它使用SVD分解使用函數sklearn.utils.extmath.svd_flip()來糾正這一點,並執行跨越算法相同的約定。由於歷史的原因,PCA()從來沒有此修復程序(但也許這應該...)

一般情況下,這是不是擔心 - 只是一個SVD算法的限制,通常實施。

在附加的註釋,我發現因爲分配給恰好這類問題的重視PC的權重(和參數的權重一般的)危險。數值/實現細節不應該影響你的分析結果,但很多時候很難判斷數據的結果是什麼,以及你用於勘探的算法的結果。我知道這是一項家庭作業,而不是一個選擇,但重要的是要記住這些事情!