Validación cruzada y búsqueda de cuadrícula para la selección de modelos en Python

Un proceso típico de aprendizaje automático implica entrenar diferentes modelos en el conjunto de datos y seleccionar el que tenga el mejor rendimiento. Sin embargo, evaluando el desempeño...

Introducción

Un proceso típico de aprendizaje automático implica entrenar diferentes modelos en el conjunto de datos y seleccionar el que tenga el mejor rendimiento. Sin embargo, evaluar el rendimiento del algoritmo no siempre es una tarea sencilla. Hay varios factores que pueden ayudarlo a determinar qué algoritmo funciona mejor. Uno de esos factores es el rendimiento en el conjunto de validación cruzada y otro factor es la elección de parámetros para un algoritmo.

En este artículo exploraremos estos dos factores en detalle. Primero estudiaremos qué es la validación cruzada, por qué es necesaria y cómo realizarla a través de la biblioteca Scikit-Aprender de Python. Luego pasaremos al Algoritmo de búsqueda de cuadrícula y veremos cómo se puede usar para seleccionar automáticamente los mejores parámetros para un algoritmo.

Validación cruzada {#validación cruzada}

Normalmente, en un proceso de aprendizaje automático, los datos se dividen en conjuntos de entrenamiento y prueba; el conjunto de entrenamiento se usa luego para entrenar el modelo y el conjunto de prueba se usa para evaluar el rendimiento de un modelo. Sin embargo, este enfoque puede conducir a problemas de varianza. En palabras más simples, un problema de varianza se refiere al escenario en el que nuestra precisión obtenida en una prueba es muy diferente a la precisión obtenida en otro conjunto de pruebas usando el mismo algoritmo.

La solución a este problema es usar Validación cruzada de K-Fold para la evaluación del desempeño donde K es cualquier número . El proceso de K-Fold Cross-Validation es sencillo. Divides los datos en K pliegues. Fuera de los pliegues K, los conjuntos K-1 se usan para entrenamiento, mientras que el conjunto restante se usa para pruebas. El algoritmo se entrena y prueba K veces, cada vez que se usa un nuevo conjunto como conjunto de prueba, mientras que los conjuntos restantes se usan para el entrenamiento. Finalmente, el resultado de K-Fold Cross-Validation es el promedio de los resultados obtenidos en cada conjunto.

Supongamos que queremos realizar una validación cruzada de 5 veces. Para hacerlo, los datos se dividen en 5 conjuntos, por ejemplo, los llamamos SET A, SET B, SET C, SET D y SET E. El algoritmo se entrena y prueba K veces. En el primer pliegue, SET A a SET D se usan como conjunto de entrenamiento y SET E se usa como conjunto de prueba, como se muestra en la siguiente figura:

Cross validation{.img-responsive}

En el segundo pliegue, el CONJUNTO A, el CONJUNTO B, el CONJUNTO C y el CONJUNTO E se usan para entrenamiento y el CONJUNTO D se usa como prueba. El proceso continúa hasta que cada conjunto se usa al menos una vez para entrenamiento y una vez para prueba. El resultado final es el promedio de los resultados obtenidos utilizando todos los pliegues. De esta manera podemos deshacernos de la varianza. Usando la desviación estándar de los resultados obtenidos de cada pliegue, podemos encontrar la varianza en el resultado general.

Validación cruzada con Scikit-Learn {#validación cruzada con scikitlearn}

En esta sección utilizaremos la validación cruzada para evaluar el desempeño de Algoritmo de bosque aleatorio para la clasificación. El problema que vamos a resolver es predecir la calidad del vino en base a 12 atributos. Los detalles del conjunto de datos están disponibles en el siguiente enlace:

https://archive.ics.uci.edu/ml/datasets/wine+quality

Solo estamos usando los datos para el vino tinto en este artículo.

Siga estos pasos para implementar la validación cruzada usando Scikit-Learn:

1. Importación de bibliotecas requeridas

El siguiente código importa algunas de las bibliotecas requeridas:

1
2
import pandas as pd
import numpy as np

2. Importación del conjunto de datos

Descargue el conjunto de datos, que está disponible en línea en este enlace:

https://www.kaggle.com/piyushgoyal443/conjunto-de-datos-de-vino-tinto

Una vez que lo hayamos descargado, colocamos el archivo en la carpeta "Datasets" de nuestra unidad "D" por el bien de este artículo. El nombre del conjunto de datos es "winequality-red.csv". Tenga en cuenta que deberá cambiar la ruta del archivo para que coincida con la ubicación en la que guardó el archivo en su computadora.

Ejecute el siguiente comando para importar el conjunto de datos:

1
dataset = pd.read_csv(r"D:/Datasets/winequality-red.csv", sep=';')

El conjunto de datos estaba separado por punto y coma, por lo tanto, hemos pasado el atributo ";" al parámetro "sep" para que pandas pueda analizar correctamente el archivo.

3. Análisis de datos

Ejecute el siguiente script para obtener una descripción general de los datos:

1
dataset.head()

La salida se ve así:

  fixed acidity   volatile acidity   citric acid   residual sugar   chlorides   free sulfur dioxide   total sulfur dioxide   density   pH     sulphates   alcohol   quality

0 7,4 0,70 0,00 1,9 0,076 11,0 34,0 0,9978 3,51 0,56 9,4 5 1 7,8 0,88 0,00 2,6 0,098 25,0 67,0 0,9968 3,20 0,68 9,8 5 2 7,8 0,76 0,04 2,3 0,092 15,0 54,0 0,9970 3,26 0,65 9,8 5 3 11,2 0,28 0,56 1,9 0,075 17,0 60,0 0,9980 3,16 0,58 9,8 6 4 7,4 0,70 0,00 1,9 0,076 11,0 34,0 0,9978 3,51 0,56 9,4 5

4. Preprocesamiento de datos {#4preprocesamiento de datos}

Ejecute el siguiente script para dividir los datos en conjuntos de etiquetas y características.

1
2
X = dataset.iloc[:, 0:11].values
y = dataset.iloc[:, 11].values

Dado que estamos utilizando la validación cruzada, no necesitamos dividir nuestros datos en conjuntos de entrenamiento y prueba. Queremos todos los datos en el conjunto de entrenamiento para que podamos aplicar la validación cruzada en eso. La forma más sencilla de hacer esto es establecer el valor del parámetro test_size en 0. Esto devolverá todos los datos en el conjunto de entrenamiento de la siguiente manera:

1
2
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0, random_state=0)

5. Escalando los datos

Si observa el conjunto de datos, notará que no está bien escalado. Por ejemplo, las columnas "acidez volátil" y "ácido cítrico" tienen valores entre 0 y 1, mientras que la mayoría del resto de las columnas tienen valores más altos. Por lo tanto, antes de entrenar el algoritmo, necesitaremos reducir nuestros datos.

Aquí usaremos la clase StandardScalar.

1
2
3
4
from sklearn.preprocessing import StandardScaler
feature_scaler = StandardScaler()
X_train = feature_scaler.fit_transform(X_train)
X_test = feature_scaler.transform(X_test)

6. Entrenamiento y validación cruzada {#6entrenamiento y validación cruzada}

El primer paso en la fase de entrenamiento y validación cruzada es simple. Solo tiene que importar la clase de algoritmo de la biblioteca sklearn como se muestra a continuación:

1
2
from sklearn.ensemble import RandomForestClassifier
classifier = RandomForestClassifier(n_estimators=300, random_state=0)

A continuación, para implementar la validación cruzada, se puede utilizar el método cross_val_score de la biblioteca sklearn.model_selection. cross_val_score devuelve la precisión de todos los pliegues. Los valores de 4 parámetros deben pasarse a la clase cross_val_score. El primer parámetro es el estimador, que básicamente especifica el algoritmo que desea utilizar para la validación cruzada. El segundo y tercer parámetro, X e y, contienen los datos X_train e y_train, es decir, características y etiquetas. Finalmente, el número de pliegues se pasa al parámetro cv como se muestra en el siguiente código:

1
2
from sklearn.model_selection import cross_val_score
all_accuracies = cross_val_score(estimator=classifier, X=X_train, y=y_train, cv=5)

Una vez que haya ejecutado esto, simplemente imprimamos las precisiones devueltas por cinco pliegues por el método cross_val_score llamando a print en all_accuracies.

1
print(all_accuracies)

Producción:

1
[ 0.72360248  0.68535826  0.70716511  0.68553459  0.68454259 ]

Para encontrar el promedio de todas las precisiones, simplemente use el método mean() del objeto devuelto por el método cross_val_score como se muestra a continuación:

1
print(all_accuracies.mean())

El valor medio es 0,6972, o 69,72%.

Finalmente, encontremos la desviación estándar de los datos para ver el grado de variación en los resultados obtenidos por nuestro modelo. Para hacerlo, llame al método std() en el objeto all_accuracies.

1
print(all_accuracies.std())

El resultado es: 0.01572 que es 1.57%. Esto es extremadamente bajo, lo que significa que nuestro modelo tiene una varianza muy baja, lo que en realidad es muy bueno, ya que significa que la predicción que obtuvimos en un conjunto de prueba no es casual. Más bien, el modelo funcionará de manera más o menos similar en todos los conjuntos de prueba.

Búsqueda en cuadrícula para selección de parámetros {#búsqueda en cuadrícula para selección de parámetros}

Un modelo de aprendizaje automático tiene dos tipos de parámetros. El primer tipo de parámetros son los parámetros que se aprenden a través de un modelo de aprendizaje automático, mientras que el segundo tipo de parámetros son los hiperparámetros que pasamos al modelo de aprendizaje automático.

En la última sección, al predecir la calidad del vino, usamos el algoritmo Random Forest. El número de estimadores que usamos para el algoritmo fue 300. De igual forma en algoritmo KNN tenemos que especificar el valor de K y para algoritmo SVM tenemos que especificar el tipo de Kernel. Estos estimadores, el valor K y Kernel, son todos tipos de hiperparámetros.

Normalmente establecemos aleatoriamente el valor de estos hiperparámetros y vemos qué parámetros dan como resultado el mejor rendimiento. Sin embargo, la selección aleatoria de los parámetros para el algoritmo puede ser exhaustiva.

Además, no es fácil comparar el rendimiento de diferentes algoritmos configurando aleatoriamente los hiperparámetros porque un algoritmo puede funcionar mejor que otro con un conjunto diferente de parámetros. Y si se cambian los parámetros, el algoritmo puede funcionar peor que los otros algoritmos.

Por lo tanto, en lugar de seleccionar aleatoriamente los valores de los parámetros, un mejor enfoque sería desarrollar un algoritmo que encuentre automáticamente los mejores parámetros para un modelo en particular. Grid Search es uno de esos algoritmos.

Búsqueda en cuadrícula con Scikit-Learn

Implementemos el algoritmo de búsqueda de cuadrícula con la ayuda de un ejemplo. La secuencia de comandos de esta sección debe ejecutarse después de la secuencia de comandos que creamos en la última sección.

Para implementar el algoritmo Grid Search, necesitamos importar la clase GridSearchCV de la biblioteca sklearn.model_selection.

El primer paso que debe realizar es crear un diccionario de todos los parámetros y su correspondiente conjunto de valores que desea probar para obtener el mejor rendimiento. El nombre de los elementos del diccionario corresponde al nombre del parámetro y el valor corresponde a la lista de valores del parámetro.

Vamos a crear un diccionario de parámetros y sus valores correspondientes para nuestro algoritmo Random Forest. Los detalles de todos los parámetros para el algoritmo de bosque aleatorio están disponibles en los [Documentos de Scikit-Learn](http://scikit-learn.org/stable/modules/generated/sklearn.ensemble.RandomForestClassifier.html#sklearn.ensemble. Clasificador de bosque aleatorio).

Para ello, ejecute el siguiente código:

1
2
3
4
5
grid_param = {
    'n_estimators': [100, 300, 500, 800, 1000],
    'criterion': ['gini', 'entropy'],
    'bootstrap': [True, False]
}

Tome una mirada cuidadosa en el código anterior. Aquí creamos el diccionario grid_param con tres parámetros n_estimators, criterion y bootstrap. Los valores de los parámetros que queremos probar se pasan en la lista. Por ejemplo, en el script anterior queremos encontrar qué valor (entre 100, 300, 500, 800 y 1000) proporciona la mayor precisión.

De manera similar, queremos encontrar qué valor da como resultado el rendimiento más alto para el parámetro criterio: "gini" o "entropía"? El algoritmo Grid Search básicamente prueba todas las combinaciones posibles de valores de parámetros y devuelve la combinación con la mayor precisión. Por ejemplo, en el caso anterior, el algoritmo verificará 20 combinaciones (5 x 2 x 2 = 20).

El algoritmo de búsqueda en cuadrícula puede ser muy lento, debido a la cantidad potencialmente enorme de combinaciones para probar. Además, la validación cruzada aumenta aún más el tiempo de ejecución y la complejidad.

Una vez que se crea el diccionario de parámetros, el siguiente paso es crear una instancia de la clase GridSearchCV. Debe pasar valores para el parámetro estimator, que básicamente es el algoritmo que desea ejecutar. El parámetro param_grid toma como parámetro el diccionario de parámetros que acabamos de crear, el parámetro scoring toma las métricas de rendimiento, el parámetro cv corresponde al número de pliegues, que es 5 en nuestro caso, y finalmente el n_jobs El parámetro se refiere a la cantidad de CPU que desea usar para la ejecución. Un valor de -1 para el parámetro n_jobs significa que utiliza toda la potencia informática disponible. Esto puede ser útil si tiene una gran cantidad de datos.

Echa un vistazo al siguiente código:

1
2
3
4
5
gd_sr = GridSearchCV(estimator=classifier,
                     param_grid=grid_param,
                     scoring='accuracy',
                     cv=5,
                     n_jobs=-1)

Una vez que se inicializa la clase GridSearchCV, el último paso es llamar al método fit de la clase y pasarle el conjunto de entrenamiento y prueba, como se muestra en el siguiente código:

1
gd_sr.fit(X_train, y_train)

Este método puede tardar algún tiempo en ejecutarse porque tenemos 20 combinaciones de parámetros y una validación cruzada de 5 veces. Por lo tanto, el algoritmo se ejecutará un total de 100 veces.

Una vez que el método completa la ejecución, el siguiente paso es verificar los parámetros que devuelven la mayor precisión. Para hacerlo, imprima el atributo sr.best_params_ del objeto GridSearchCV, como se muestra a continuación:

1
2
best_parameters = gd_sr.best_params_
print(best_parameters)

Producción:

1
{'bootstrap': True, 'criterion': 'gini', 'n_estimators': 1000}

El resultado muestra que la precisión más alta se logra cuando n_estimators es 1000, bootstrap es True y criterion es "gini".

Nota: sería una buena idea agregar más estimadores y ver si el rendimiento aumenta aún más desde que se eligió el valor más alto permitido de n_estimadores.

El último y último paso del algoritmo Grid Search es encontrar la precisión obtenida utilizando los mejores parámetros. Anteriormente teníamos una precisión media del 69,72 % con 300 n_estimadores.

Para encontrar la mejor precisión lograda, ejecute el siguiente código:

1
2
best_result = gd_sr.best_score_
print(best_result)

La precisión lograda es: 0.6985 de 69.85% que es solo un poco mejor que 69.72%. Para mejorar esto aún más, sería bueno probar los valores de otros parámetros del algoritmo Random Forest, como max_features, max_ depth, max_leaf_nodes, etc. para ver si la precisión mejora aún más o no.

Yendo más lejos: proyecto de extremo a extremo portátil

¿Tu naturaleza inquisitiva te hace querer ir más allá? Recomendamos consultar nuestro Proyecto guiado: ["Predicción práctica del precio de la vivienda: aprendizaje automático en Python"](https://wikihtp.com/courses/hands-on-house- precio-predicción-aprendizaje-máquina-en-python/#cta){target="_blank"}.

[](https://wikihtp.com/ cursos/predicción-de-precio-de-la-casa-práctica-aprendizaje-de-máquina-en-python/#cta)

En este proyecto guiado, aprenderá a crear potentes modelos tradicionales de aprendizaje automático, así como modelos de aprendizaje profundo, utilizar Ensemble Learning y capacitar a los meta-aprendices para predecir los precios de la vivienda a partir de una bolsa de modelos Scikit-Learn y Keras.

Con Keras, la API de aprendizaje profundo creada sobre Tensorflow, experimentaremos con arquitecturas, crearemos un conjunto de modelos apilados y entrenaremos una red neuronal meta-aprendizaje (modelo de nivel 1) para averiguar el precio de un casa.

El aprendizaje profundo es sorprendente, pero antes de recurrir a él, se recomienda intentar resolver el problema con técnicas más simples, como los algoritmos de aprendizaje superficial. Nuestro rendimiento de referencia se basará en un algoritmo de Regresión de bosque aleatorio. Además, exploraremos la creación de conjuntos de modelos a través de Scikit-Learn a través de técnicas como embalaje y votación.

Este es un proyecto integral y, como todos los proyectos de aprendizaje automático, comenzaremos con Análisis exploratorio de datos, seguido de Preprocesamiento de datos y, finalmente, Creación de modelos de aprendizaje superficial y Profundo para ajustarse a los datos que hemos explorado y limpiado previamente.

Conclusión

En este artículo estudiamos dos técnicas muy utilizadas para la evaluación del rendimiento y la selección del modelo de un algoritmo. La validación cruzada K-Fold se puede utilizar para evaluar el rendimiento de un modelo mediante el manejo del problema de varianza del conjunto de resultados. Además, para identificar el mejor algoritmo y los mejores parámetros, podemos usar el algoritmo Grid Search. ch.