Aprendizaje automático

Aprendizaje automático con Scikit-learn #1: Clasificación

Contenido

Este artículo no está pensado para ser una extensa documentación acerca de los fundamentos teóricos del aprendizaje automático o machine learning. No obstante, queremos dar una breve introducción para que cualquier persona con interés y ganas de aprender sea capaz de seguir el artículo, entender los conceptos y saber para qué sirve el machine learning y los algoritmos de clasificación.

Breve introducción

En el mundo digitalizado que vivimos se generan toneladas de datos en cada instante. Por eso manejar esas cantidades de información es importante. El aprendizaje automático son el conjunto de técnicas y algoritmos que nos permite encontrar información oculta o patrones en esa información y usarla en nuestro beneficio.

Un ejemplo sencillo de esto sería lo siguiente. Imaginemos que disponemos de una serie de datos acerca de una familia de flores tipo Iris y queremos determinar a que familia (Setosa, Versicolor, Virgínica) pertenece una flor en base a esos datos. Esto es posible mediante el uso de algoritmos de aprendizaje automático (en concreto métodos de clasificación), como veremos a continuación.

Hemos visto como el problema planteado consistía en la clasificación de una flor tipo Iris dentro de una de sus subfamilias en base a una serie de atributos que hemos recolectado. Este es un tipo de problema clásico denominado problema de clasificación dentro del aprendizaje automático. Otro problema muy común dentro de este campo es la predicción de un valor numérico en base a una serie de valores. Este problema es conocido como un problema de regresión dentro del campo del machine learning. Estos son dos problemas típico de la materia aunque existen otros muchos que podemos encontrar: agrupación o clustering, detección de anomalías, etc.

Aprendizaje supervisado o no supervisado

Dentro de los problemas podemos agruparlos en tipos dependiendo de si en el proceso de aprendizaje automático que estamos realizando disponemos de la solución deseada al problema o no. Es decir, supongamos un problema de aprendizaje automático en el que queremos detectar cuándo un correo electrónico es correo basura o no. Disponemos en nuestro dataset de una serie de atributos y sabemos a priori si cada ejemplo del mismo es o no correo basura. En este caso diremos que es un problema de aprendizaje supervisado, puesto que sabemos el resultado deseado de cada ejemplo. A este valor deseado (correo basura o no basura) se le denomina etiqueta.

Por otro lado, diremos que un sistema de aprendizaje automático es no supervisado, cuándo el dataset no contenga ninguna etiqueta deseada en el mismo. Por ejemplo, supongamos un dataset de usuarios con una serie de atributos, en el que queremos detectar grupos de usuarios parecidos. Este sería un problema de aprendizaje no supervisado típico denominado agrupamiento o clustering.

Clustering de usuarios en dos grupos más próximos.
Clustering de usuarios en dos grupos más próximos.

Podemos distinguir dos fases diferentes en un proyecto de aprendizaje: el entrenamiento y la inferencia. Definiremos el primero como el proceso que hace que el algoritmo use como entrada el dataset que hemos definido y obtenga una serie de valores o pesos para el modelo matemático definido. Por otro lado, el proceso de inferencia consiste en, una vez el modelo ya entrenado, presentarle un nuevo ejemplo que no pertenece al dataset de entrenamiento y el modelo nos de una respuesta para el mismo.

En cualquier caso existen documentos que el lector podrá usar para ampliar conocimientos y que se han definido en la bibliografía del presente documento.

Usando Python y scikit-learn para aprendizaje automático y clasificación

Para trabajar con proyectos de aprendizaje automático es buena idea usar el lenguaje de programación Python, que es uno de los más sencillos de usar y nos permitirá prototipar de forma rápida y eficaz nuestros entrenamientos e implementar sistemas completos de machine learning listos para usar en sistemas en producción. Por otro lado, una de las principales librerías que se usa para implementar sistemas de aprendizaje automático es scikit-learn. Esta librería nos permitirá usar los principales algoritmos y modelos para resolver problemas de aprendizaje automático como los expuestos anteriormente.

Seleccionando un dataset

Para trabajar con algoritmos de machine learning, es imprescindible el uso de una fuente de datos a partir de la cual los métodos que vamos a emplear sean capaces de obtener los patrones e información oculta. Estos conjuntos de datos también se conocen como dataset.

Puesto que vamos a trabajar con Scikit-learn, usaremos alguno de los dataset que esta librería ya tiene integrado. Podemos echar un vistazo a los principales dataset que ya tiene integrada la librería.

En este artículo vamos a realizar un ejemplo de sistema de clasificación usando el Iris dataset que ya está integrado dentro de la librería. Este dataset contiene ejemplos con cuatro atributos numéricos:

  1. Longitud del sépalo en centímetros.
  2. Anchura del sépalo en centímetros.
  3. Longitud del pétalo en centímetros.
  4. Anchura del pétalo en centímetros.

Cada uno de los ejemplos se clasifica en tres posibles tipos de Iris: Iris-Setosa, Iris-Versicolor e Iris-Virgínica.

Utilizamos este dataset ya que es sencillo en el número de atributos y que todos los atributos son numéricos y por lo tanto no necesitan transformación alguna. Cosa que dejaremos para futuros artículo más avanzados.

Una nota acerca de la medida de rendimiento en problemas de clasificación

Uno de los principales puntos a tener en cuenta cuándo estamos entrenando un sistema de aprendizaje automático es seleccionar una medida que nos indique lo bueno o malo que es el mismo. Esto es lo que llamamos medida de rendimiento. Dependiendo del tipo de problema de machine learning que estamos tratando de resolver tendremos que utilizar una medida de rendimiento u otra. Para problemas de clasificación la medida más básica se define como exactitud o accuracy. Podemos definirla como:

Definición matemática de exactitud o accuracy
Definición matemática de exactitud o accuracy

Siendo las predicciones correctas aquellos casos en los que el sistema haya acertado la clase a la que pertenece nuestro caso de ejemplo sobre el total de predicciones hecha. Así, si tenemos una exactitud de un 91% quiere decir que el sistema acierta 91 de cada 100 predicciones que hace.

Entrando en materia

Vamos a empezar a trabajar de forma práctica con scikit-learn y para ello primero tendremos que usar un entorno que disponga de Python y permisos para instalar paquetes. La forma más sencilla de trabajar con esto es usar un entorno virtual en Python o usar un entorno como Google Collab que nos permite ejecutar código sin necesidad instalar nada en nuestra máquina. Sigue las explicaciones del artículo de forma tranquila ya que todo el código que aparece en el mismo estará disponible en nuestro repositorio de código.

En un primer paso inicial necesitaremos instalar la librería scikit-learn en nuestro entorno virtual o notebook de Colab. Para ellos ejecutaremos el siguiente código:

pip install scikit-learn

El sistema nos informará de que todo es correcto y podremos acceder a la versión instalada mediante el código Python:

import sklearn as skl
print(skl.__version__)

Para importar el dataset que hemos elegido anteriormente deberemos usar la función que scikit-learn nos ha habilitado para ello y que realizaremos con el siguiente código:

# Importamos el dataset
import sklearn.datasets
dataset = sklearn.datasets.load_iris()

Dentro de la variable dataset tendremos la descripción del dataset (daaset.DESCR) una lista con el nombre de los atributos de cada una de la instancias (dataset.feature_names), la ruta del fichero que contiene el dataset (dataset.filename), una matriz con los valores de los atributos para cada una de las instancias (dataset.data), un array con el valor numérico de la clasificación objetivo (dataset.target) y el nombre de la clase para cada valor numérico (dataset.target_names). Con esto ya estamos listos para empezar a trabajar.

Separando el dataset

Una de los principales cosas a tener en cuenta cuándo estamos preparando el dataset para realizar un entrenamiento es que deberemos separar las instancias o ejemplos del mismo en varios grupos. En los casos más simples será necesario formar al menos dos grupos de instancias: entrenamiento y test. Estos dos grupos de se utilizan para fines diferentes. Así, el grupo de instancias de entrenamiento se usa para entrenar o ajustar el modelo matemático que estamos usando para resolver nuestro problema de aprendizaje automático; mientras que el grupo de test se usa para evaluar el desempeño del modelo con un conjunto de datos que no se hayan usado para entrenar.

Existen otras formas de separar un dataset para empezar un entrenamiento, pero lo dejaremos para artículos más avanzados. Generalmente hablando se suele separar el dataset en un 20% para test (o menos si el número de instancias del mismo es alto). Para realizar esta labor tenemos algunas funciones que nos ayudan en scikit-learn. Usaremos la variable X para referirnos a los atributos de las instancias y la variable y para referirnos a las respuestas que esperamos de nuestro sistema o etiquetas. Así para realizar la separación de nuestro dataset haremos lo siguiente:

from sklearn.model_selection import train_test_split

# Renombramos los valores para que X sean los atributos e Y sean las respuestas del sistema
X = dataset.data
y = dataset.target

# Realizamos la partición de nuestro dataset en un conjunto de entrenamiento y otro de test (20%)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

Entrenando el modelo de clasificación

Como hemos comentado anteriormente, una vez tenemos nuestro dataset separado de forma conveniente, tendremos que entrenar usando algunos de los algoritmos de clasificación de los que disponemos en scikit-learn. Podríamos usar cualquiera de la gran variedad que nos proporciona la librería. En nuestro caso usaremos un clasificador conocido como Máquina de Vector de Soporte (Support Vector Machine), en adelante SVM por sus siglas en inglés. Este clasificador es uno de los más empleados en tareas de clasificación en aprendizaje automático, ya que. ofrece muy buenos resultados de forma general y para la mayoría de datasets. Por lo tanto, siempre que estemos tratando de resolver un problema de clasificación, será un algoritmo a probar para ver que resultados da. En nuestro caso utilizaremos el siguiente código:

from sklearn.svm import SVC

# Creamos el clasificador SVM lineal
classifier =  SVC(kernel="linear", C=0.025)

# Realizamos el entrenamiento
classifier.fit(X_train, y_train)

# Obtenemos el accuracy de nuestro modelo para el conjunto de test
print(classifier.score(X_test, y_test))

Podemos apreciar en el código que primero importamos el clasificador que vamos a usar desde scikit-learn. Los parámetros que pasamos al clasificador modifican el comportamiento del mismo y se denominan hiperparámetros. En el caso que nos ocupa se establecen el tipo de kernel usado (tipo lineal) y un valor de regularización. Estos hiperparámetros quedan fuera del alcance del artículo actual y se dejan para artículos más avanzados en la materia.

En la siguiente línea podemos ver que el entrenamiento se realiza usando el método fit del clasificador, al que le pasamos el conjunto de entrenamiento que hemos separado previamente (X_train, y_train). Por último podemos imprimir el accuracy que ha obtenido nuestro modelo una vez entrenado haciendo uso del valor devuelto por la función score del clasificador, a la que le pasaremos como parámetro el conjunto de test que hemos separado previamente.

Una vuelta de tuerca más sobre el entrenamiento en problemas de clasificación

Si hemos seguido el artículo de forma correcta hasta aquí, ya tendríamos un clasificador entrenado que nos ha debido dar un valor de accuracy de unos 96.6%. Como hemos definido anteriormente, esto significa que, nuestro clasificador ha sido capaz de obtener más de 96 valores de predicción correctos de cada 100 para el conjunto de datos de test que le hemos pasado.

Sin embargo hay algo que deberíamos tener en cuenta con respecto al entrenamiento. Imaginemos que por casualidad, al separar nuestro dataset en los conjuntos de entrenamiento y test, en el conjunto de test caen muchas instancias que para el modelo son más difíciles de clasificar. Lo que ocurrirá es que el valor de accuracy que vamos a obtener es más bajo que el que normalmente obtendríamos si el conjunto de entrenamiento hubiera sido otro. Por este motivo, realizar entrenamientos con un sólo conjunto de entrenamiento y test es problemático y en general se desaconseja. En la siguiente imagen podemos ver una simplificación de una separación de conjuntos descompensada.

Creación simple de un conjunto de entrenamiento y test para clasificación
Creación simple de un conjunto de entrenamiento y test

En la figura podemos ver que en el conjunto de test sólo han caído instancias azules, lo que puede resultar en unos valores de accuracy totalmente distorsionados, si por algún motivo nuestro clasificador en bueno o malo clasificando esas instancias.

Otras formas de entrenamiento

Existen otras formas más convenientes de realizar los entrenamientos en aprendizaje automático. Una de las más habituales y sólidas es utilizar la validación cruzada o cross validation. Esto en general, parte de la idea de realizar N separaciones diferentes de conjuntos de entrenamiento y test. Posteriormente realizamos N entrenamientos diferentes con cada conjunto de entrenamiento y N validaciones con cada conjunto de test correspondiente. En este caso obtendremos N valores de exactitud o accuracy diferentes para cada conjunto de entrenamiento/test. Nuestro accuracy final sería la media de todos los valores de exactitud que hemos calculado. De esta forma evitamos que, por algún motivo, hayamos obtenidos un conjunto de entrenamiento/test que nos de resultados engañosos; y obtenemos una medida más fiable de como es el modelo entrenado.

Un ejemplo de validación cruzada o cross validation

En la siguiente figura podemos ver un ejemplo con el dataset de la figura anterior:

Validación cruzada usando 4 ejecuciones con diferentes grupos de entrenamiento y test
Validación cruzada usando 4 ejecuciones con diferentes grupos de entrenamiento y test

En la figura se puede apreciar como seleccionamos un conjunto de entrenamiento diferente en cada una de los cuatro entrenamientos diferentes que realizamos. Posteriormente la evaluación se realizará sobre el conjunto de evaluación que no ha sido seleccionado como conjunto de entrenamiento en esa iteración. De esta forma seleccionamos cuatro conjuntos de test que contienen una variedad mayor de clases de instancias y que mitigarán los efectos descritos anteriormente.

Para utlizar la validación cruzada usaremos el siguiente código:

# Importamos la función de entrenamiento y validación cruzada
from sklearn.model_selection import cross_val_score
nScores = cross_val_score(classifier, X, y, cv=10)
# Nos devuelve un array de tipo Numpy. Podemos usar el método mean para obtener la media de los valores devueltos
nScores.mean()

En el código primero importamos la función cross_val_score que usaremos para realizar la validación cruzada. Este método recibe como parámetro el clasificador que se va a entrenar y evaluar. También recibe los atributos de las instancias que tenemos en nuestro dataset (X) y las clases etiquetadas (y).

Por último, utilizamos el parámetro cv que indica el número de particiones de entrenamiento/test que vamos a usar para realizar entrenamientos y evaluación. La función nos devuelve un array (Numpy) del mismo tamaño indicado por cv, que contienen los accurracy de cada entrenamiento/validación hecha. Para obtener el valor medio de los valores del array, usaremos el método mean del array Numpy obtenido. Este será, el valor de accuracy obtenido de nuestro modelo, que será más fiable que la exactitud obtenida en el primer entrenamiento que hemos realizado. En el caso que nos ocupa hemos obtenido un valor de accuracy de 0.94, que es un poco menor que el primero que obtuvimos y que representa de una forma más fidedigna la calidad del clasificador que hemos entrenado.

Resumiendo

Hemos visto una introducción breve al tema de aprendizaje automático aplicado a un problema concreto de clasificación. Para ello hemos realizado la obtención de un dataset de ejemplo que viene por defecto con Scikit-learn. Se ha visto como la necesidad de separa un dataset en varios conjuntos de entrenamiento y test y diferentes formas para realizar el entrenamiento de un clasificador de scikit-learn; viendo que diferencias existen entre realizar el entrenamiento y validación de una u otra forma.

Todo el código que se ha usado en este artículo está disponible en el repositorio de Github de la web, concretamente en https://github.com/AprendeConEjemplos/aprendizaje-automatico-con-scikit-learn/tree/main/01_intro_clasificacion.

En futuros artículos realizaremos una entrada más profunda en más temas de machine learning y veremos más ejemplos haciendo uso de scikit-learn y otras librerías.

Para cualquier sugerencia o crítica dispones de un formulario de sugerencias más abajo que puedes usar libremente.

Bibliografía

  1. https://es.wikipedia.org/wiki/Aprendizaje_autom%C3%A1tico

Sugerencias

    captcha

    Comparte el artículo

    Entradas relacionadas