35 votos

PCA en numpy y sklearn produce resultados diferentes

¿Estoy malinterpretando algo? Este es mi código

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

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

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

He conservado los 3 componentes pero parece que no me permite conservar mis datos originales.

¿Puedo saber por qué es así?

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

34voto

zowens Puntos 1417

La diferencia se debe a que decomposition.PCA no estandariza sus variables antes de hacer el PCA, mientras que en su cálculo manual llama a StandardScaler para hacer la normalización. De ahí que se observe esta diferencia: ¿PCA sobre correlación o covarianza?

Si sustituye

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 sólo hasta la orden de los PC. Esto se debe a que cuando se ejecuta

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

se obtienen valores propios no necesariamente en orden decreciente. Yo obtengo

array([ 0.07168571,  2.49382602,  1.43448827])

Por lo tanto, tendrá que pedirlos manualmente. Sklearn lo hace por ti.


En cuanto a la reconstrucción de las variables originales, véase ¿Cómo invertir el ACP y reconstruir las variables originales a partir de varios componentes principales?

20voto

kathystehl Puntos 124

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

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)

hay que ordenar los valores propios (y los vectores propios correspondientes) de forma descendente

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

a = np.dot(x, evecs) 

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

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X