Python para todos: Tutorial de PCA en 5 sencillos pasos

Paloma Recuero de los Santos    13 junio, 2018

Seguimos nuestra estrategia de “aprender haciendo” (Learning by Doing). En este caso, después de haber introducido el concepto de selección de características en el post anterior, vamos a trabajar sobre un ejemplo concreto en Python. Aplicaremos la técnica de Análisis de Componentes Principales (PCA– Principal Component Analysis) para reducir la dimensionalidad de un dataset y así simplificar la modelización posterior. 

Esta técnica es de gran interés, porque se aplica a una gran variedad de casos. Por ejemplo, en seguridad informática se han desarrollado métodos de detección de intrusos mediante redes neuronales, basados en reducción de características. También se utiliza en problemas de clasificación de píxeles en base a su color, que son la base de muchas aplicaciones de análisis de imágenes para sistemas biométricos de reconocimiento facial, detección de defectos de fabricación en procesos industriales, etiquetado de tejidos en imágenes médicas, localización de regiones en imágenes por satélite etc. Incluso se pueden encontrar aplicaciones de PCA a investigación genética o predicción de ganancias en el mercado de valores.  

El dataset clásico que se utiliza para explicar esta técnica es un viejo conocido para nosotros, el de clasificación de iris. En Kaggle, Github o webs de machine learning y ciencia de datos podemos encontrar distintas versiones de este ejemplo, lo cual siempre es interesante para comparar y aprender. Lo que no es tan fácil es encontrar ejemplos en español. Hay un post muy interesante de David Solís sobre este caso, escrito en R, que podéis encontrar aquí. Nosotros, lo haremos en Python. 

1. Planteamiento del problema

Si recordamos del ejemplo anterior, el dataset de clasificación de iris, que podemos descargar del repositorio UCI, contiene las medidas de 150 flores que pertenecen a 3 especies diferentes:

  1. Iris-setosa
  2. Iris-versicolor
  3. Iris-virginica

Este dataset se usa como datos de entrenamiento para un modelo de machine learning cuyo objetivo es determinar de forma automática la especie a la que pertenece una determinada flor, a partir de las medidas 4 atributos o características. En particular, la longitud y la anchura de sus pétalos y sépalos expresadas en centímetros. Por tanto, se trata de un problema de 4 dimensiones, en el que la variable objetivo (target) es la especie. Los datos se pueden representar en forma de una matriz de 150 filas (los datos de cada flor), por 4 columnas (las medidas de sus pétalos/sépalos). La quinta, corresponde a la variable objetivo, la especie.

Figura 2: Tabla de características.

2. Los 5 pasos del proceso PCA.

Los pasos que vamos a dar y que explicaremos detalladamente son los siguientes:

  1. Cargar los datos
  2. Normalizarlos
  3. Obtener los autovectores y autovalores a partir de la matriz de covarianza
  4. Seleccionar los autovectores correspondientes a las componentes principales
  5. Proyectar el dataset original sobre el nuevo espacio de dimensión < 4

2.1 Carga de los datos y librerías

En este primer paso, como hicimos en el experimento anterior, cargamos las librerías que vamos a usar, cargamos el conjunto de datos (desde el repositorio UCI) en un dataframe df , y les echamos un vistazo con el último comando. Obtenemos la siguiente representación de los datos:

Obtenemos la siguiente representación de los datos:

Figura 3: Aspecto del dataset.

A continuación, dividimos el conjunto de datos en dos partes.

(Este post, explica de forma sencilla cómo usar iloc para seleccionar filas o columnas de una matriz).

2.2 Normalización

Cuando las distintas características o atributos de un dataset están expresadas en distintas escalas se hace patente la necesidad de normalizar sus valores. En este caso, en el que las medidas de sépalos y pétalos están expresadas en centímetros, no sería imprescindible. Sin embargo, como ya comentamos en el post anterior (en forma de una de las limitaciones del PCA), al aplicar esta técnica se asume que los datos de trabajado tienen una distribución gaussiana o normal.  Por tanto, aplicamos a los datos una transformación de normalización de forma que su media sea igual a 0, y su varianza=1. Para ello, usaremos la transformación Standardscaler de sklearn.

2.3 Cálculo de autovectores y autovalores (eigenvector/eigenvalue).

 En el post anterior explicamos que los autovectores son las direcciones en las que la varianza de los datos es mayor.  Recordemos que, en teoría de probabilidad, la varianza  de una variable aleatoria es una medida de dispersión (definida como la esperanza del cuadrado de la desviación de dicha variable respecto a su media). Por tanto, las direcciones en las que la varianza es mayor,  representan la esencia principal de la información contenida en el dataset, por eso se les llama componentes principales. Al igual que un autovector es una dirección, el autovalor es un número, que representa el valor de la varianza sobre ese autovector. Por ello, para encontrar las componentes principales que condensen esa esencia de la información del dataset, calcularemos primero la matriz de covarianza, que nos da la medida de dispersión conjunta entre variables.

 Para ello, usaremos la función Covariance Matrix de la librería Numpy.

Y obtenemos el siguiente resultado:

Figura 4: Matriz de covarianza.

Como vimos en el post anterior, las direcciones sobre las que la varianza es mayor (=mayor dispersión de los datos=mayor información) se corresponden con los autovectores, vectores propios o eigenvectors de esta matriz. Por tanto, el siguiente paso consiste en calcular estas direcciones.

Y obtenemos el siguiente resultado:

Figura 5: Autovalores y Autovectores.

Si lo que queremos es reducir la dimensionalidad del dataset, perdiendo la menor información posible, descartaremos los autovectores cuyos autovalores sean más bajos, ya que son aquellos que menos información aportan al conjunto global. Para ello, lo que se hace es ordenarlos por parejas de autovector, autovalor.

Obtenemos:

Autovalores en orden descendiente.
Figura 6: Autovalores en orden descendiente.

2.4 Seleccionamos los los autovectores correspondientes a las componentes principales

El objetivo de este caso es proyectar este dataset 4D en un espacio de menor dimensionalidad, para mejorar la eficiencia de cálculo, al mismo tiempo que se retiene la mayor parte de la información. La pregunta clave será ¿cuál va ser este valor? ¿3D?¿2D?¿1D?. Para ello seguiremos el siguiente proceso.

Una vez ordenados los autovalores, que recordamos son una medida de la varianza de los datos, la cuestión es decidir, cuál es el menor número de autovectores o componentes principales, con el que podemos expresar “la esencia principal” de la información contenida en ese dataset. Para ello, usaremos un métrica que se conoce como “varianza explicada”, que muestra cuánta varianza se puede atribuir a cada una de estas componentes principales.

Para ello ejecutaremos el siguiente código

(Si queréis cambiar el aspecto de la gráfica, echad un vistazo a la galería de estilos para Matplotlib )-

Obtenemos este resultado:

Figura 7: Representación gráfica de la varianza explicada. 

En la gráfica se aprecia claramente que la mayor parte de la varianza (en torno al 70%) corresponde a la primera componente. La segunda acumula algo más del 20% de la varianza, mientras que la tercera puede ser descartada sin perder demasiada información, ya que las dos primeras componentes explican más del 90% de la varianza.

2.5  Proyectamos los datos sobre un espacio de dimensionalidad menor.

En este ejemplo, construiremos una matriz de proyección que convertirá el conjunto de datos inicial (de 4D) en un conjunto de datos de 2D centrado en las sus componentes principales (las direcciones de los autovectores correspondientes). De esta forma, la tarea de interpretar los patrones de información contenidos en los datos, será mucho más sencilla. Para ello, primero creamos la matriz de proyección a partir de los autovalores principales con el siguiente código:

Y, por último, representamos gráficamente el nuevo espacio de datos, con éstas últimas líneas:

Obteniendo, este resultado:

Figura 8: Representación gráfica del dataset en un espacio 2D.

Y ¡ya está!. Hemos conseguido reducir el conjunto de datos de trabajo inicial a un conjunto de datos de dos dimensiones que aún así conserva la información más esencial. de forma que nos resultará mucho más sencillo el trabajo de crear un modelo de clasificación a partir de estos datos. Como ya indicamos anteriormente, es una técnica muy frecuente, ya que es sencilla y facilita mucho el trabajo posterior.

Los post de esta segunda miniserie son:

También puedes seguirnos en nuestras redes sociales:  @Telefonica@LUCA_D3@ElevenPaths