2016-08-05 55 views
0

Ich trainierte, um einige PCA Rekonstruktionen von MNIST auf Python zu machen und sie mit meiner (alten) Rekonstruktion in Maltab zu vergleichen und ich entdeckte zufällig, dass meine Rekonstruktion nicht übereinstimmt. Nach einigem Debugging entschied ich mich, ein einzigartiges Merkmal der Hauptkomponenten eines jeden zu drucken, um zu zeigen, ob sie gleich waren und ich zu meiner Überraschung entdeckte, dass sie nicht gleich waren. Ich drucke die Summe aller Komponenten und ich habe verschiedene Nummern. Ich habe folgende in Matlab:Warum stimmen die Hauptkomponentenwerte von Scipy und MATLAB nicht überein?

[coeff, ~, ~, ~, ~, mu] = pca(X_train); 
U = coeff(:,1:K) 
U_fingerprint = sum(U(:)) 
%print 31.0244 

und in Python/scipy:

pca = pca.fit(X_train) 
U = pca.components_ 
print 'U_fingerprint', np.sum(U) 
# prints 12.814 

warum die twi PCA ist nicht den gleichen Wert Berechnung?


Alle meine Versuche und lösen Sie dieses Problem:

So wie ich das entdeckt wurde, weil, wenn ich meine MNIST Bilder wurde die Rekonstruktion, die Python-Rekonstruktionen, wo viel viel näher an ihre Originalbilder durch eine Menge. Ich habe Fehler von 0.0221556788645 in Python, während in MATLAB ich Fehler der Größe 29.07578 bekam. Um herauszufinden, woher der Unterschied kommt, habe ich mich entschieden, die Datensätze mit einem Fingerabdruck zu versehen (vielleicht wurden sie anders normiert). Also habe ich zwei unabhängige Kopien des MNIST Datensatz (die durch Teile meines 255 normiert wurden) und bekam die Fingerabdrücke (alle Zahlen in Datensatz Summieren):

print np.sum(x_train) # from keras 
print np.sum(X_train)+np.sum(X_cv) # from TensorFlow 
6.14628e+06 
6146269.1585420668 

, die (im Wesentlichen) gleich (eine Kopie von Tensorflow MNIST und der andere von Keras MNIST, Anmerkung MNIST Zugdatensatz hat ungefähr 1000 weniger Trainingssatz, also müssen Sie die fehlenden anhängen). Zu meiner Überraschung hatte meine MATLAB Daten den gleichen Fingerabdruck:

data_fingerprint = sum(X_train(:)) 
% prints data_fingerprint = 6.1463e+06 

die Datensätze sind Sinn genau gleich. Gut, also sind die Normalisierungsdaten nicht das Problem.

In meinem MATLAB-Skript ich manuell wie folgt die Rekonstruktion tatsächlich Berechnung:

U = coeff(:,1:K) 
X_tilde_train = (U * U' * X_train); 
train_error_PCA = (1/N_train)*norm(X_tilde_train - X_train ,'fro')^2 
%train_error_PCA = 29.0759 

so dachte ich, dass das Problem sein könnte, weil ich die Schnittstelle Python wurde mit ergaben die Rekonstruktionen wie in zur Berechnung:

pca = PCA(n_components=k) 
pca = pca.fit(X_train) 
X_pca = pca.transform(X_train) # M_train x K 
#print 'X_pca' , X_pca.shape 
X_reconstruct = pca.inverse_transform(X_pca) 
print 'tensorflow error: ',(1.0/X_train.shape[0])*LA.norm(X_reconstruct_tf - X_train) 
print 'keras error: ',(1.0/x_train.shape[0])*LA.norm(X_reconstruct_keras - x_train) 
#tensorflow error: 0.0221556788645 
#keras error: 0.0212030354818 

was zu unterschiedlichen Fehlerwerten 0.022 vs 29.07 führt, schockierender Unterschied!

So ich die exakte Rekonstruktion Formel in meinem Python-Skript zu codieren entschieden:

pca = PCA(n_components=k) 
pca = pca.fit(X_train) 
U = pca.components_ 
print 'U_fingerprint', np.sum(U) 
X_my_reconstruct = np.dot( U.T , np.dot(U, X_train.T)) 
print 'U error: ',(1.0/X_train.shape[0])*LA.norm(X_reconstruct_tf - X_train) 
# U error: 0.0221556788645 

zu meiner Überraschung, es hat die gleichen Fehler wie mein MNIST Fehler Computing durch die Schnittstelle. Daraus folgere ich, dass ich nicht das Missverständnis von PCA habe, von dem ich dachte, dass ich es hätte.

All dies führte zu mir zu überprüfen, was die Hauptkomponenten tatsächlich wo und zu meiner Überraschung scipy und MATLAB haben unterschiedliche Fingerabdruck für ihre PCA-Werte.

Weiß jemand, warum oder was los ist?


Als warren vorgeschlagen, die PKA Komponenten (Eigenvektoren) können unterschiedliche Vorzeichen haben. Nach einem Fingerabdruck tun, indem alle Komponenten in Größenordnung nur entdeckte ich sie den gleichen Fingerabdruck haben:

[coeff, ~, ~, ~, ~, mu] = pca(X_train); 
K=12; 
U = coeff(:,1:K) 
U_fingerprint = sumabs(U(:)) 
% U_fingerprint = 190.8430 

und für Python:

k=12 
pca = PCA(n_components=k) 
pca = pca.fit(X_train) 
print 'U_fingerprint', np.sum(np.absolute(U)) 
# U_fingerprint 190.843 

die die Differenz bedeutet, wegen der sein muss, unterschiedliches Vorzeichen des (pca) U-Vektors. Was ich sehr überraschend finde, ich dachte, das sollte einen großen Unterschied machen, ich habe nicht einmal daran gedacht, dass es einen großen Unterschied machen würde. Ich schätze ich lag falsch?

+0

Wie viele Komponenten geben beide Versionen zurück? Vergleicht man die Dokumentation, könnte das ein Unterschied sein, der das beobachtete Verhalten erklären könnte. – rubenvb

+0

@rubenvb sie sind beide 12 (offensichtlich das gleiche oder sonst wäre es dummer Fehler meinerseits, ich werde den github-Code morgen früh für die Skripte für die Menschen zu beurteilen). –

+0

In MATLAB Variablen sind Spalte Bürgermeister und in Python Reihe Bürgermeister. Stellen Sie sicher, dass Sie die PCA nicht in der transponierten Matrix berechnen. –

Antwort

2

Ich weiß nicht, ob das das Problem ist, aber es könnte sicherlich sein. Hauptkomponentenvektoren sind wie Eigenvektoren: Wenn Sie den Vektor mit -1 multiplizieren, ist es immer noch ein gültiger PCA-Vektor. Einige der von Matlab berechneten Vektoren haben möglicherweise ein anderes Vorzeichen als die in Python berechneten Vektoren. Das wird zu sehr unterschiedlichen Summen führen.

Zum Beispiel hat die Matlab Dokumentation dieses Beispiel:

coeff = pca(ingredients) 

coeff = 

    -0.0678 -0.6460 0.5673 0.5062 
    -0.6785 -0.0200 -0.5440 0.4933 
    0.0290 0.7553 0.4036 0.5156 
    0.7309 -0.1085 -0.4684 0.4844 

ich meine eigene Python PCA-Code haben, und mit dem gleichen Eingang wie in Matlab, erzeugt es diesen Koeffizienten-Array:

[[ 0.0678 0.646 -0.5673 0.5062] 
[ 0.6785 0.02 0.544 0.4933] 
[-0.029 -0.7553 -0.4036 0.5156] 
[-0.7309 0.1085 0.4684 0.4844]] 

Anstatt also einfach das Koeffizientenfeld zu summieren, versuchen Sie, die Absolutwerte der Koeffizienten zu summieren. Stellen Sie alternativ sicher, dass alle Vektoren vor dem Summieren die gleiche Vorzeichenkonvention haben. Sie könnten das zum Beispiel tun, indem Sie jede Spalte mit dem Vorzeichen des ersten Elements in dieser Spalte multiplizieren (vorausgesetzt, dass keine von ihnen Null ist).

+0

scheint so zu sein, dass die beiden Hauptkomponentenmatrizen (Eigenvektor) den gleichen Fingerabdruck hatten, wie ich es jetzt vorgeschlagen habe, als ich den neuen Fingerabdruck mit absolutem Wert berechnete. Bedeutet das, dass die Rekonstruktion falsch berechnet wird, weil das Vorzeichen der Eigenvektoren nicht übereinstimmt? –

+0

Das Zeichen sollte keinen Unterschied machen, da die Rekonstruktionen über X_reconstruct = U * U.T * X erfolgen, die das Vorzeichen aufheben. –

+1

Wenn ich genauer auf meinen Code schaue, merkt man, dass ich den Verlust der Norm 2 berechnet habe, aber dann quadratisch rooted (oder genauer gesagt: nicht quadrieren) und der andere berechnete den quadratischen Fehler, aber ich quadrierte den Fehler . Das berücksichtigte die Unterschiede. Danke für die Hilfe! : D –