PCA en numpy y sklearn produce resultados diferentes

21

¿Estoy malinterpretando algo? Este es mi codigo

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

Salida:

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

Usando métodos numpy

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

Salida

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.

¿Puedo saber por qué es así?

Si quiero recuperar mi matriz original, ¿qué debo hacer?

aceminer
fuente
Su código numpy es incorrecto en mi humilde opinión (también, utiliza lo Xque no está definido). Vuelve a verificar tus matemáticas .
Anony-Mousse -Reinstale a Monica el
Estoy usando ipython notebook, así que solo pude copiar por celdas. Mis matemáticas están mal? Qué parte @ Anony-Mousse
aceminer
@ Anony-Mousse Sí, me di cuenta de mi error pero aún no coincide
aceminer
@aceminer Tengo curiosidad por qué calcula la matriz de covarianza de x_std.T, no x_std?
Evgeni Nabokov
@EvgeniNabokov ha pasado demasiado tiempo. Sry ya no me acuerdo
aceminer

Respuestas:

21

La diferencia se debe a decomposition.PCAque no estandariza sus variables antes de hacer PCA, mientras que en su cálculo manual llama StandardScalerpara hacer la estandarización. Por lo tanto, está observando esta diferencia: ¿ PCA en correlación o covarianza?

Si reemplazas

pca.fit_transform(x)

con

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

obtendrá el mismo resultado que con el cálculo manual ...

... pero solo hasta el orden de las PC. Eso es porque cuando corres

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

obtienes valores propios no necesariamente en orden decreciente. yo obtengo

array([ 0.07168571,  2.49382602,  1.43448827])

Por lo tanto, querrá ordenarlos manualmente. Sklearn hace eso por ti.


Con respecto a la reconstrucción de variables originales, consulte ¿Cómo revertir PCA y reconstruir variables originales a partir de varios componentes principales?

ameba dice Reinstate Monica
fuente
Solo me gustaría comprobarlo. ¿Es realmente necesario estandarizar la matriz por su desviación estándar? Vi ejemplos en los que no lo hacen
aceminer
No es necesario , es solo una forma de hacerlo. Vea el enlace que puse en el primer párrafo: stats.stackexchange.com/questions/53 : realmente se trata de esta pregunta. Si estandariza, hace PCA en correlaciones. Si no lo hace, realiza PCA en covarianzas.
ameba dice Reinstate Monica
9

Aquí hay una buena implementación con discusión y explicación de PCA en python. Esta implementación lleva al mismo resultado que el scikit PCA. Este es otro indicador de que su PCA está equivocado.

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)

necesita ordenar los valores propios (y los vectores propios en consecuencia) descendentes

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

a = np.dot(x, evecs) 

En general, le recomiendo que verifique su código implementando un ejemplo simple (lo más simple posible) y calculando a mano los resultados correctos (y los resultados intermedios). Esto te ayuda a identificar el problema.

Nikolas Rieble
fuente
1
Amo esta respuesta. ¡Resolvió mi problema!
Jinhua Wang