sklearn component python machine-learning scikit-learn pca

python - component - Recuperar las características de los nombres de explanation_variance_ratio_ en PCA con sklearn



pca sklearn (4)

Estoy tratando de recuperarme de una PCA realizada con scikit-learn, cuyas funciones se seleccionan como relevantes .

Un ejemplo clásico con el conjunto de datos IRIS.

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_

Esto regresa

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

¿Cómo puedo recuperar qué dos características permiten estas dos varianzas explicadas entre el conjunto de datos? Dicho de otra manera, ¿cómo puedo obtener el índice de estas características en iris.feature_names?

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

Gracias de antemano por tu ayuda.


Dado su estimador ajustado pca , los componentes se encuentran en pca.components_ , que representan las direcciones de mayor varianza en el conjunto de datos.


Editar: como otros han comentado, puede obtener los mismos valores del atributo documentation .

Cada componente principal es una combinación lineal de las variables originales:

donde X_i s son las variables originales, y Beta_i s son los pesos correspondientes o los llamados coeficientes.

Para obtener los pesos, simplemente puede pasar la matriz de identidad al método de transform :

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

Cada columna de la matriz de coef anterior muestra los pesos en la combinación lineal que obtiene el componente principal correspondiente:

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

Por ejemplo, arriba muestra que el segundo componente principal ( PC-2 ) se alinea principalmente con el sepal width , que tiene el mayor peso de 0.926 en valor absoluto;

Dado que los datos se normalizaron, puede confirmar que los componentes principales tienen la varianza 1.0 que es equivalente a cada vector de coeficiente que tiene la norma 1.0 :

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

También se puede confirmar que los componentes principales se pueden calcular como el producto punto de los coeficientes anteriores y las variables originales:

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

Tenga en cuenta que necesitamos usar numpy.allclose lugar del operador de igualdad regular, debido a un error de precisión de coma flotante.


Esta información está incluida en el atributo pca : components_ . Tal como se describe en la documentation , pca.components_ genera una matriz de [n_components, n_features] , para [n_components, n_features] cómo los componentes están linealmente relacionados con las diferentes características que tiene que:

Nota : cada coeficiente representa la correlación entre un par particular de componente y función

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

IMPORTANTE: Como comentario lateral, tenga en cuenta que el signo de PCA no afecta su interpretación ya que el signo no afecta la varianza contenida en cada componente. Solo los signos relativos de las características que forman la dimensión PCA son importantes. De hecho, si ejecuta nuevamente el código de PCA, puede obtener las dimensiones de PCA con los signos invertidos. Para una intuición sobre esto, piense en un vector y su negativo en el espacio tridimensional; ambos representan esencialmente la misma dirección en el espacio. Verifique esta publicación para mayor referencia.


La forma en que se formula esta pregunta me recuerda un malentendido sobre el Análisis de componentes principales cuando estaba tratando de resolverlo por primera vez. Me gustaría revisarlo aquí con la esperanza de que los demás no pasen tanto tiempo en un camino a la nada como lo hice antes de que el centavo finalmente cayera.

La noción de nombres de características "en recuperación" sugiere que PCA identifica aquellas características que son más importantes en un conjunto de datos. Eso no es estrictamente cierto.

PCA, según tengo entendido, identifica las características con mayor varianza en un conjunto de datos, y luego puede usar esta calidad del conjunto de datos para crear un conjunto de datos más pequeño con una pérdida mínima de poder descriptivo. Las ventajas de un conjunto de datos más pequeño es que requiere menos potencia de procesamiento y debe tener menos ruido en los datos. Pero las características de mayor varianza no son las características "mejores" o "más importantes" de un conjunto de datos, en la medida en que se puede decir que tales conceptos existen.

Para llevar esa teoría a los aspectos prácticos del código de muestra de @ Rafa arriba:

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

considera lo siguiente:

post_pca_array = pca.fit_transform(data_scaled) print data_scaled.shape (150, 4) print post_pca_array.shape (150, 2)

En este caso, post_pca_array tiene las mismas 150 filas de datos que data_scaled , pero las cuatro columnas de data_scaled se han reducido de cuatro a dos.

El punto crítico aquí es que las dos columnas (o componentes, para ser terminológicamente consistentes) de post_pca_array no son las dos "mejores" columnas de data_scaled . Son dos columnas nuevas, determinadas por el algoritmo detrás del módulo PCA sklearn.decomposition . La segunda columna, PC-2 en el ejemplo de @ Rafa, está informada por sepal_width más que cualquier otra columna, pero los valores en PC-2 y data_scaled[''sepal_width''] no son los mismos.

Como tal, si bien es interesante averiguar cuánto contribuyó cada columna en los datos originales a los componentes de un conjunto de datos posterior a la PCA, la noción de "recuperar" los nombres de las columnas es un poco engañosa y me engañó durante mucho tiempo. La única situación en la que habría una coincidencia entre las columnas post-PCA y originales sería si el número de componentes principales se estableciera en el mismo número que las columnas en el original. Sin embargo, no tendría sentido usar el mismo número de columnas porque los datos no habrían cambiado. Solo hubieras ido allí para regresar, como fuera.