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)']
よろしくお願いします。
この情報は、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 を確認してください。
編集:他の人がコメントしたように、 .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]
たとえば、上記の例では、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
を使用する必要があることに注意してください。
この質問の言い回しは、私が最初にそれを理解しようとしていたときの主成分分析の誤解を思い出させます。ここで、ペニーが最終的に落ちる前に、他の人が私が行ったようにどこにも行かない道に多くの時間を費やさないことを望んで、それを通過したいです。
機能名の「回復」という概念は、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.decomposition
のPCA
モジュールの背後にあるアルゴリズムによって決定されます。 2番目の列、@ Rafaの例のPC-2
は、他の列よりもsepal_width
によって通知されますが、PC-2
とdata_scaled['sepal_width']
の値は同じではありません。
そのため、元のデータの各列がPCA後のデータセットのコンポーネントにどの程度寄与したかを知ることは興味深いですが、列名の「回復」という概念は少し誤解を招くものであり、長い間誤解されていました。 PCA後の列と元の列が一致する唯一の状況は、主成分の数が元の列と同じ数に設定されている場合です。ただし、データが変更されていないため、同じ数の列を使用しても意味がありません。それがあったように、あなたは再び戻ってくるためにそこに行っただけだったでしょう。
近似推定器pca
が与えられた場合、コンポーネントはpca.components_
は、データセット内で最高の分散の方向を表します。
- 取得する 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
です。