[英]Randomized PCA .explained_variance_ratio_ sums to greater than one in sklearn 0.15.0
[英]Recovering features names of explained_variance_ratio_ in PCA with sklearn
我正在嘗試從使用 scikit-learn 完成的 PCA 中恢復,哪些特征被選為相關的。
IRIS 數據集的經典示例。
import pandas as pd
import pylab as pl
from sklearn import datasets
from sklearn.decomposition import PCA
# load dataset
iris = datasets.load_iris()
df = pd.DataFrame(iris.data, columns=iris.feature_names)
# normalize data
df_norm = (df - df.mean()) / df.std()
# PCA
pca = PCA(n_components=2)
pca.fit_transform(df_norm.values)
print pca.explained_variance_ratio_
這返回
In [42]: pca.explained_variance_ratio_
Out[42]: array([ 0.72770452, 0.23030523])
我怎樣才能恢復哪兩個特征允許這兩個數據集之間的解釋差異? 換個說法,我如何在 iris.feature_names 中獲取此功能的索引?
In [47]: print iris.feature_names
['sepal length (cm)', 'sepal width (cm)', 'petal length (cm)', 'petal width (cm)']
在此先感謝您的幫助。
此信息包含在pca
屬性中: components_
。 如文檔中所述, pca.components_
輸出一個[n_components, n_features]
數組,因此要了解組件與不同功能的線性關系,您必須:
注意:每個系數代表特定對組件和特征之間的相關性
import pandas as pd
import pylab as pl
from sklearn import datasets
from sklearn.decomposition import PCA
# load dataset
iris = datasets.load_iris()
df = pd.DataFrame(iris.data, columns=iris.feature_names)
# normalize data
from sklearn import preprocessing
data_scaled = pd.DataFrame(preprocessing.scale(df),columns = df.columns)
# PCA
pca = PCA(n_components=2)
pca.fit_transform(data_scaled)
# Dump components relations with features:
print(pd.DataFrame(pca.components_,columns=data_scaled.columns,index = ['PC-1','PC-2']))
sepal length (cm) sepal width (cm) petal length (cm) petal width (cm)
PC-1 0.522372 -0.263355 0.581254 0.565611
PC-2 -0.372318 -0.925556 -0.021095 -0.065416
重要提示:作為旁注,請注意 PCA 符號不影響其解釋,因為該符號不影響每個組件中包含的方差。 只有形成 PCA 維度的特征的相對符號才是重要的。 事實上,如果您再次運行 PCA 代碼,您可能會得到符號反轉的 PCA 尺寸。 為了直觀地了解這一點,請考慮 3-D 空間中的向量及其負數 - 兩者本質上都表示空間中的相同方向。 檢查此帖子以獲取進一步參考。
編輯:正如其他人評論的那樣,您可能會從.components_
屬性中獲得相同的值。
每個主成分都是原始變量的線性組合:
其中X_i
s 是原始變量,而Beta_i
s 是相應的權重或所謂的系數。
要獲得權重,您可以簡單地將單位矩陣傳遞給transform
方法:
>>> i = np.identity(df.shape[1]) # identity matrix
>>> i
array([[ 1., 0., 0., 0.],
[ 0., 1., 0., 0.],
[ 0., 0., 1., 0.],
[ 0., 0., 0., 1.]])
>>> coef = pca.transform(i)
>>> coef
array([[ 0.5224, -0.3723],
[-0.2634, -0.9256],
[ 0.5813, -0.0211],
[ 0.5656, -0.0654]])
上面的coef
矩陣的每一列都顯示了線性組合中的權重,以獲得相應的主成分:
>>> pd.DataFrame(coef, columns=['PC-1', 'PC-2'], index=df.columns)
PC-1 PC-2
sepal length (cm) 0.522 -0.372
sepal width (cm) -0.263 -0.926
petal length (cm) 0.581 -0.021
petal width (cm) 0.566 -0.065
[4 rows x 2 columns]
例如,上圖顯示第二主成分( PC-2
)大部分與sepal width
對齊,其絕對值最高權重為0.926
;
由於數據已歸一化,您可以確認主成分的方差為1.0
,這相當於每個系數向量的范數為1.0
:
>>> np.linalg.norm(coef,axis=0)
array([ 1., 1.])
也可以確認主成分可以計算為上述系數和原始變量的點積:
>>> np.allclose(df_norm.values.dot(coef), pca.fit_transform(df_norm.values))
True
請注意,由於浮點精度錯誤,我們需要使用numpy.allclose
而不是常規相等運算符。
這個問題的措辭方式讓我想起了當我第一次試圖弄清楚它時對主成分分析的誤解。 我想在這里通讀一遍,希望其他人不會像我在一分錢最終落下之前那樣,在無路可走的路上花費太多時間。
“恢復”特征名稱的概念表明 PCA 可以識別數據集中最重要的特征。 這不完全正確。
據我了解,PCA 識別數據集中方差最大的特征,然后可以使用數據集的這種質量來創建一個較小的數據集,同時將描述能力的損失降至最低。 較小數據集的優勢在於它需要較少的處理能力,並且數據中的噪聲較小。 但是最大方差的特征並不是數據集的“最佳”或“最重要”特征,只要這些概念可以說是完全存在的。
將該理論帶入上述@Rafa 示例代碼的實用性中:
# load dataset
iris = datasets.load_iris()
df = pd.DataFrame(iris.data, columns=iris.feature_names)
# normalize data
from sklearn import preprocessing
data_scaled = pd.DataFrame(preprocessing.scale(df),columns = df.columns)
# PCA
pca = PCA(n_components=2)
pca.fit_transform(data_scaled)
考慮以下:
post_pca_array = pca.fit_transform(data_scaled)
print data_scaled.shape
(150, 4)
print post_pca_array.shape
(150, 2)
在這種情況下, post_pca_array
具有作為相同的150行數據data_scaled
,但data_scaled
的四列已經從四個減少到兩個。
這里的關鍵點是,兩列-或部件,要在術語一致-的post_pca_array
不是兩個“最佳”列data_scaled
。 它們是兩個新列,由sklearn.decomposition
的PCA
模塊背后的算法確定。 sepal_width
示例中的第二列PC-2
由sepal_width
通知的sepal_width
比任何其他列sepal_width
多,但PC-2
和data_scaled['sepal_width']
中的值不相同。
因此,雖然找出原始數據中的每一列對 post-PCA 數據集的組成部分的貢獻很有趣,但“恢復”列名的概念有點誤導,而且肯定誤導了我很長時間。 后 PCA 和原始列之間匹配的唯一情況是主成分的數量設置為與原始列中的列數相同。 但是,使用相同數量的列沒有意義,因為數據不會改變。 你去那里只會再次回來,就像它一樣。
獲取 PC 上the most important feature name
:
from sklearn.decomposition import PCA
import pandas as pd
import numpy as np
np.random.seed(0)
# 10 samples with 5 features
train_features = np.random.rand(10,5)
model = PCA(n_components=2).fit(train_features)
X_pc = model.transform(train_features)
# number of components
n_pcs= model.components_.shape[0]
# get the index of the most important feature on EACH component i.e. largest absolute value
# using LIST COMPREHENSION HERE
most_important = [np.abs(model.components_[i]).argmax() for i in range(n_pcs)]
initial_feature_names = ['a','b','c','d','e']
# get the names
most_important_names = [initial_feature_names[most_important[i]] for i in range(n_pcs)]
# using LIST COMPREHENSION HERE AGAIN
dic = {'PC{}'.format(i+1): most_important_names[i] for i in range(n_pcs)}
# build the dataframe
df = pd.DataFrame(sorted(dic.items()))
這打印:
0 1
0 PC1 e
1 PC2 d
所以在PC1命名的功能e
是最重要和PC2的d
。
給定您的擬合估計量pca
,將在pca.components_
找到pca.components_
,它們表示數據集中方差最大的方向。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.