web-dev-qa-db-ja.com

sklearnを使用したPCAでのexplain_variance_ratio_の機能名の回復

Scikit-learnで行われたPCAから回復しようとしています。which機能はrelevantとして選択されています。

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])

どの2つの特徴がデータセット間でこれらの2つの説明された分散を可能にするかを回復するにはどうすればよいですか?別様に、どうすればiris.feature_namesでこの機能のインデックスを取得できますか?

In [47]: print iris.feature_names
['sepal length (cm)', 'sepal width (cm)', 'petal length (cm)', 'petal width (cm)']

よろしくお願いします。

53
mazieres

この情報は、pca属性に含まれています:components_documentation で説明されているように、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コードを再度実行すると、符号が反転したPCA寸法が得られる場合があります。これについての直観のために、3D空間でのベクトルとそのネガティブについて考えてみてください。両方とも本質的に空間で同じ方向を表しています。詳細については、 this post を確認してください。

63
Rafa

編集:他の人がコメントしたように、 .components_ 属性から同じ値を取得できます。


各主成分は、元の変数の線形結合です。

pca-coef

ここで、X_isは元の変数であり、Beta_isは対応する重みまたは係数と呼ばれます。

重みを取得するには、単純に単位行列を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]

たとえば、上記の例では、2番目の主成分(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 を使用する必要があることに注意してください。

45
behzad.nouri

この質問の言い回しは、私が最初にそれを理解しようとしていたときの主成分分析の誤解を思い出させます。ここで、ペニーが最終的に落ちる前に、他の人が私が行ったようにどこにも行かない道に多くの時間を費やさないことを望んで、それを通過したいです。

機能名の「回復」という概念は、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にはdata_scaledと同じ150行のデータがありますが、data_scaledの4列は4列から2列に削減されています。

ここでの重要な点は、post_pca_arrayの2つの列(つまり、用語的に一貫性のあるコンポーネント)がdata_scaledの2つの「最良」列ではないことです。これらは2つの新しい列であり、sklearn.decompositionPCAモジュールの背後にあるアルゴリズムによって決定されます。 2番目の列、@ Rafaの例のPC-2は、他の列よりもsepal_widthによって通知されますが、PC-2data_scaled['sepal_width']の値は同じではありません。

そのため、元のデータの各列がPCA後のデータセットのコンポーネントにどの程度寄与したかを知ることは興味深いですが、列名の「回復」という概念は少し誤解を招くものであり、長い間誤解されていました。 PCA後の列と元の列が一致する唯一の状況は、主成分の数が元の列と同じ数に設定されている場合です。ただし、データが変更されていないため、同じ数の列を使用しても意味がありません。それがあったように、あなたは再び戻ってくるためにそこに行っただけだったでしょう。

19
amunnelly

近似推定器pcaが与えられた場合、コンポーネントはpca.components_は、データセット内で最高の分散の方向を表します。

4
eickenberg

重要な機能は、より多くのコンポーネントに影響を与えるため、コンポーネントの絶対値/係数/負荷が大きくなります。

- 取得する the most important feature name PCの場合

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です。

0
serafeim