Wiederherstellen von Feature-Namen von EXPLAIN_Varianance_Ratio_ in PCA mit sklearn

77

Ich versuche, mich von einer PCA zu erholen, die mit scikit-learn erstellt wurde und deren Funktionen als relevant ausgewählt wurden .

Ein klassisches Beispiel mit IRIS-Datensatz.

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_

Dies kehrt zurück

In [42]: pca.explained_variance_ratio_
Out[42]: array([ 0.72770452,  0.23030523])

Wie kann ich wiederherstellen, welche beiden Funktionen diese beiden erklärten Abweichungen im Datensatz zulassen? Anders gesagt, wie kann ich den Index dieser Funktionen in iris.feature_names erhalten?

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

Vielen Dank im Voraus für Ihre Hilfe.

mazieres
quelle
4
pca.components_ist das, wonach Sie suchen.
ExAres
Wenn Sie das single most important feature nameauf einem bestimmten PC (oder auf allen PCs) erhalten möchten, lesen Sie meine Antwort am Ende dieser Seite.
Seralouk

Antworten:

85

Diese Informationen sind im pcaAttribut enthalten : components_. Wie in der Dokumentation beschrieben , wird pca.components_ein Array von ausgegeben [n_components, n_features], um zu ermitteln, wie Komponenten linear mit den verschiedenen Funktionen verknüpft sind:

Hinweis : Jeder Koeffizient repräsentiert die Korrelation zwischen einem bestimmten Komponenten- und Merkmalspaar

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

WICHTIG: Beachten Sie als Nebenkommentar, dass das PCA-Zeichen seine Interpretation nicht beeinflusst, da das Zeichen die in jeder Komponente enthaltene Varianz nicht beeinflusst. Nur die relativen Anzeichen von Merkmalen, die die PCA-Dimension bilden, sind wichtig. Wenn Sie den PCA-Code erneut ausführen, erhalten Sie möglicherweise die PCA-Abmessungen mit invertierten Vorzeichen. Denken Sie für eine Intuition darüber an einen Vektor und sein Negativ im 3D-Raum - beide repräsentieren im Wesentlichen die gleiche Richtung im Raum. Überprüfen Sie diesen Beitrag für weitere Referenz.

Rafa
quelle
Komponenten sind tatsächlich Kombinationen von Merkmalen, so dass jedes bestimmte Merkmal (bis zu einem gewissen Grad) mit verschiedenen Komponenten korreliert ist ....
Rafa
3
Angenommen, Sie möchten wissen, welches Originalmerkmal am wichtigsten war. Sollten Sie nur die absoluten Werte nehmen und summieren? Was ich meine ist, beginnend mit der letzten Zeile der Antwort: pd.DataFrame (pca.components_, column = data_scaled.columns, index = ['PC-1', 'PC-2']). Abs (). Sum (Achse = 0), was zu den dortigen Werten führt: 0,894690 1,188911 0,602349 0,631027. Können wir hiermit sagen, dass die Kelchblattbreite am wichtigsten war, gefolgt von der Kelchblattlänge?
Guido
10
Um zu verstehen, welche Funktionen wichtig sind, müssen Sie auf die Korrelationen achten. Zum Beispiel sind die Kelchblattbreite und PC-2 stark (umgekehrt) korreliert, da der Korrelationskoeffizient -0,92 beträgt. Andererseits sind Blütenblattlänge und PC-2 überhaupt nicht korreliert, da der Corr-Coef -0,02 beträgt. PC-2 wächst also mit abnehmender Kelchblattbreite und PC-2 ist unabhängig von Änderungen der Blütenblattlänge. Das heißt, für PC-2 ist die Kelchblattbreite wichtig, die Blütenblattlänge jedoch nicht. Dieselbe Analyse, die Sie für die anderen Variablen unter Berücksichtigung des Korrelationskoeffizienten durchführen können, liegt im Intervall [-1, 1]
Rafa,
Nützliche Antwort! Für meine Zwecke wollte ich, dass der Datenrahmen so geschwenkt wird, dass die Komponenten Spalten sind. Ich benutztepd.DataFrame(pca.components_.T, index=data_scaled.columns)
Laura
Wenn Sie das single most important feature nameauf einem bestimmten PC (oder auf allen PCs) erhalten möchten, lesen Sie meine Antwort am Ende dieser Seite.
Seralouk
51

Bearbeiten: Wie andere kommentiert haben, erhalten Sie möglicherweise dieselben Werte vom .components_Attribut.


Jede Hauptkomponente ist eine lineare Kombination der ursprünglichen Variablen:

pca-coef

Dabei sind X_is die ursprünglichen Variablen und Beta_is die entsprechenden Gewichte oder sogenannten Koeffizienten.

Um die Gewichte zu erhalten, können Sie einfach eine Identitätsmatrix an die transformMethode übergeben:

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

Jede Spalte der coefobigen Matrix zeigt die Gewichte in der linearen Kombination, die die entsprechende Hauptkomponente erhält:

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

Das obige Beispiel zeigt zum Beispiel, dass die zweite Hauptkomponente ( PC-2) meistens ausgerichtet ist mit sepal widthder höchsten Gewichtung des 0.926absoluten Werts;

Da die Daten normalisiert wurden, können Sie bestätigen, dass die Hauptkomponenten eine Varianz aufweisen, 1.0die jedem Koeffizientenvektor mit Norm entspricht 1.0:

>>> np.linalg.norm(coef,axis=0)
array([ 1.,  1.])

Man kann auch bestätigen, dass die Hauptkomponenten als Punktprodukt der obigen Koeffizienten und der ursprünglichen Variablen berechnet werden können:

>>> np.allclose(df_norm.values.dot(coef), pca.fit_transform(df_norm.values))
True

Beachten Sie, dass wir numpy.allcloseaufgrund des Gleitkomma-Genauigkeitsfehlers anstelle des regulären Gleichheitsoperators verwenden müssen.

behzad.nouri
quelle
3
Tolle und umfassende Antwort, vielen Dank!
Mazieres
5
Diese Identitätsmatrix ist nicht erforderlich: Ihre coefist dieselbe wie pca.components_.T. Scikit-Learn-Schätzer setzen ihre gelernten Parameter immer in öffentliche Attribute.
Fred Foo
4
Warum nicht direkt verwenden pca.components_?
ExAres
2
Die Verwendung der Identitätsmatrix funktioniert nicht, da die inverse Transformationsfunktion den empirischen Mittelwert jedes Merkmals addiert. Das Ergebnis gibt allen ursprünglichen Variablen das gleiche Gewicht (Koeffizienten). (Siehe diese Antwort ). Mit verwenden pca.components_Sie die richtige Antwort.
Rahul Murmuria
32

Die Art und Weise, wie diese Frage formuliert ist, erinnert mich an ein Missverständnis der Prinzipkomponentenanalyse, als ich zum ersten Mal versuchte, es herauszufinden. Ich würde es hier gerne durchgehen, in der Hoffnung, dass andere nicht so viel Zeit auf einer Straße ins Nirgendwo verbringen wie ich, bevor der Penny endlich gefallen ist.

Der Begriff des "Wiederherstellens" von Feature-Namen legt nahe, dass PCA die Features identifiziert, die in einem Dataset am wichtigsten sind. Das stimmt nicht ganz.

PCA identifiziert nach meinem Verständnis die Merkmale mit der größten Varianz in einem Datensatz und kann diese Qualität des Datensatzes dann verwenden, um einen kleineren Datensatz mit minimalem Verlust an Beschreibungskraft zu erstellen. Der Vorteil eines kleineren Datensatzes besteht darin, dass er weniger Rechenleistung benötigt und weniger Rauschen in den Daten aufweisen sollte. Die Merkmale der größten Varianz sind jedoch nicht die "besten" oder "wichtigsten" Merkmale eines Datensatzes, sofern davon ausgegangen werden kann, dass solche Konzepte überhaupt existieren.

Um diese Theorie in die praktischen Aspekte des obigen Beispielcodes von @ Rafa zu bringen:

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

Folgendes berücksichtigen:

post_pca_array = pca.fit_transform(data_scaled)

print data_scaled.shape
(150, 4)

print post_pca_array.shape
(150, 2)

In diesem Fall post_pca_arrayhat es die gleichen 150 Datenzeilen wie data_scaled, aber data_scaleddie vier Spalten wurden von vier auf zwei reduziert.

Der kritische Punkt hierbei ist, dass die beiden Spalten - oder Komponenten, um terminologisch konsistent zu sein - post_pca_arraynicht die beiden „besten“ Spalten von sind data_scaled. Dies sind zwei neue Spalten, die vom Algorithmus hinter sklearn.decompositiondem PCAModul bestimmt werden. Die zweite Spalte PC-2in @ Rafas Beispiel wird von sepal_widthmehr als jeder anderen Spalte informiert , aber die Werte in PC-2und data_scaled['sepal_width']sind nicht gleich.

Obwohl es interessant ist herauszufinden, wie viel jede Spalte in den Originaldaten zu den Komponenten eines Post-PCA-Datensatzes beigetragen hat, ist der Begriff des „Wiederherstellens“ von Spaltennamen ein wenig irreführend und hat mich sicherlich lange Zeit irregeführt. Die einzige Situation, in der es eine Übereinstimmung zwischen Post-PCA- und Originalspalten geben würde, wäre, wenn die Anzahl der Hauptkomponenten auf die gleiche Anzahl wie die Spalten im Original festgelegt würde. Es wäre jedoch sinnlos, dieselbe Anzahl von Spalten zu verwenden, da sich die Daten nicht geändert hätten. Du wärst nur dorthin gegangen, um sozusagen wiederzukommen.

amunnelly
quelle
Danke Aziz. Ich bin froh, dass du etwas davon bekommen hast.
amunnelly
Vielen Dank. Dies hat mir viel Zeit gespart, da ich die Funktionsweise des Algorithmus grundlegend missverstanden habe.
Thomas
8

Die wichtigen Merkmale sind diejenigen, die die Komponenten stärker beeinflussen und somit einen großen absoluten Wert / Koeffizienten / Belastung auf die Komponente haben.

Steig the most important feature nameauf die PCs :

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

Dies druckt:

     0  1
 0  PC1  e
 1  PC2  d

Schlussfolgerung / Erklärung:

Auf dem PC1 ist die genannte Funktion edie wichtigste und auf dem PC2 die d.

Seralouk
quelle
5

Angesichts Ihres angepassten Schätzers pca sich die Komponenten in pca.components_, die die Richtungen der höchsten Varianz im Datensatz darstellen.

Eickenberg
quelle