PCA in Numpy und Sklearn führt zu unterschiedlichen Ergebnissen

20

Verstehe ich etwas falsch? Das ist mein Code

mit sklearn

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from sklearn import decomposition
from sklearn import datasets
from sklearn.preprocessing import StandardScaler

pca = decomposition.PCA(n_components=3)

x = np.array([
        [0.387,4878, 5.42],
        [0.723,12104,5.25],
        [1,12756,5.52],
        [1.524,6787,3.94],
    ])
pca.fit_transform(x)

Ausgabe:

array([[ -4.25324997e+03,  -8.41288672e-01,  -8.37858943e-03],
   [  2.97275001e+03,  -1.25977271e-01,   1.82476780e-01],
   [  3.62475003e+03,  -1.56843494e-01,  -1.65224286e-01],
   [ -2.34425007e+03,   1.12410944e+00,  -8.87390454e-03]])

Mit numpy Methoden

x_std = StandardScaler().fit_transform(x)
cov = np.cov(x_std.T)
ev , eig = np.linalg.eig(cov)
a = eig.dot(x_std.T)

Ausgabe

array([[ 0.06406894,  0.94063993, -1.62373172],
   [-0.35357757,  0.7509653 ,  0.63365168],
   [ 0.29312477,  0.6710958 ,  1.11766206],
   [-0.00361615, -2.36270102, -0.12758202]])
I have kept all 3 components but it doesnt seem to allow me to retain my original data.

Darf ich wissen, warum es so ist?

Was kann ich tun, wenn ich meine ursprüngliche Matrix zurückerhalten möchte?

aceminer
quelle
Dein Zahlencode ist IMHO falsch (es wird auch Xder nicht definierte verwendet). Überprüfe deine Mathematik .
Anony-Mousse
Ich benutze Ipython Notebook, so dass ich nur nach Zellen kopieren konnte. Meine Mathematik stimmt nicht? Welcher Teil @ Anony-Mousse
aceminer
@ Anony-Mousse Ja, ich habe meinen Fehler erkannt, aber er stimmt immer noch nicht überein
aceminer
@aceminer Ich bin neugierig, warum Sie Kovarianzmatrix von x_std.T, nicht x_std berechnen?
Evgeni Nabokov
@EvgeniNabokov es ist zu lange her. Sry ich kann mich nicht erinnern
aceminer

Antworten:

21

Der Unterschied besteht darin, dass decomposition.PCAIhre Variablen vor der Durchführung der PCA nicht standardisiert werden, wohingegen Sie bei Ihrer manuellen Berechnung StandardScalerdie Standardisierung aufrufen . Sie beobachten also diesen Unterschied: PCA auf Korrelation oder Kovarianz?

Wenn Sie ersetzen

pca.fit_transform(x)

mit

x_std = StandardScaler().fit_transform(x)
pca.fit_transform(x_std)

Sie erhalten das gleiche Ergebnis wie bei der manuellen Berechnung ...

... aber nur bis zur Reihenfolge der PCs. Das liegt daran, wenn du rennst

ev , eig = np.linalg.eig(cov)

Sie erhalten Eigenwerte nicht unbedingt in absteigender Reihenfolge. Ich bekomme

array([ 0.07168571,  2.49382602,  1.43448827])

Sie sollten sie also manuell bestellen. Sklearn erledigt das für Sie.


Informationen zum Rekonstruieren von Originalvariablen finden Sie unter Umkehren von PCA und Rekonstruieren von Originalvariablen aus mehreren Hauptkomponenten.

Amöbe sagt Reinstate Monica
quelle
Ich möchte nur überprüfen. Ist es wirklich notwendig, die Matrix anhand ihrer Standardabweichung zu standardisieren? Ich habe Beispiele gesehen, wo sie es nicht tun
aceminer
Es ist nicht notwendig , es ist nur eine Möglichkeit, dies zu tun. Siehe den Link, den ich im ersten Absatz eingefügt habe : stats.stackexchange.com/questions/53 - es dreht sich wirklich alles um diese Frage. Wenn Sie standardisieren, führen Sie PCA für Korrelationen durch. Wenn Sie dies nicht tun, führen Sie PCA für Kovarianzen durch.
Amöbe sagt Reinstate Monica
9

Hier ist eine nette Implementierung mit Diskussion und Erklärung von PCA in Python. Diese Implementierung führt zum gleichen Ergebnis wie die SCIKIT-PCA. Dies ist ein weiterer Indikator dafür, dass Ihr PCA falsch ist.

import numpy as np
from scipy import linalg as LA

x = np.array([
        [0.387,4878, 5.42],
        [0.723,12104,5.25],
        [1,12756,5.52],
        [1.524,6787,3.94],
    ])

#centering the data
x -= np.mean(x, axis = 0)  

cov = np.cov(x, rowvar = False)

evals , evecs = LA.eigh(cov)

Sie müssen die Eigenwerte (und die Eigenvektoren entsprechend) absteigend sortieren

idx = np.argsort(evals)[::-1]
evecs = evecs[:,idx]
evals = evals[idx]

a = np.dot(x, evecs) 

Im Allgemeinen empfehle ich Ihnen, Ihren Code anhand eines einfachen Beispiels (so einfach wie möglich) zu überprüfen und die richtigen Ergebnisse (und Zwischenergebnisse) von Hand zu berechnen. Auf diese Weise können Sie das Problem identifizieren.

Nikolas Rieble
quelle
1
Liebe diese Antwort. Es hat mein Problem gelöst!
Jinhua Wang