scikit-learn

ScikitLearn

Tutorial ScikitLearn: Ajuste de hiperparámetros

Optimiza tus modelos de aprendizaje automático con Scikit-Learn con ajuste de hiperparámetros. Aprende a emplear la búsqueda en cuadrícula para alcanzar configuraciones óptimas.

Aprende ScikitLearn GRATIS y certifícate

Búsqueda en cuadrícula (Grid Search)

En el ajuste de hiperparámetros, la búsqueda en cuadrícula (Grid Search) es una técnica exhaustiva que permite encontrar la combinación óptima de hiperparámetros para un modelo. Consiste en definir un conjunto de valores posibles para cada hiperparámetro y evaluar el rendimiento del modelo para todas las combinaciones posibles.

El módulo GridSearchCV de Scikit-Learn automatiza este proceso, facilitando la búsqueda sistemática de los mejores hiperparámetros. Este módulo realiza una validación cruzada interna para cada combinación, garantizando una evaluación robusta del modelo.

A modo de ejemplo, supongamos que queremos optimizar un clasificador SVM ajustando los hiperparámetros C y kernel. Podemos emplear GridSearchCV de la siguiente manera:

from sklearn import datasets
from sklearn.model_selection import GridSearchCV
from sklearn.svm import SVC

# Cargar el conjunto de datos Iris
iris = datasets.load_iris()
X, y = iris.data, iris.target

# Definir el modelo base
svc = SVC()

# Definir la cuadrícula de hiperparámetros
param_grid = {
    'C': [0.1, 1, 10, 100],
    'kernel': ['linear', 'rbf', 'poly'],
    'degree': [2, 3, 4]
}

# Configurar GridSearchCV
grid_search = GridSearchCV(
    estimator=svc,
    param_grid=param_grid,
    cv=5,
    n_jobs=-1
)

# Ejecutar la búsqueda en cuadrícula
grid_search.fit(X, y)

# Mostrar los mejores hiperparámetros
print("Mejores hiperparámetros:", grid_search.best_params_)

En este script, GridSearchCV evalúa todas las combinaciones posibles de los valores especificados en param_grid. La validación cruzada con 5 particiones (cv=5) se utiliza para estimar el rendimiento de cada combinación, y el parámetro n_jobs=-1 permite paralelizar el proceso utilizando todos los núcleos disponibles.

Una vez finalizada la búsqueda, podemos acceder al modelo con los mejores hiperparámetros y utilizarlo para realizar predicciones:

# Obtener el mejor estimador
mejor_modelo = grid_search.best_estimator_

# Realizar predicciones con el mejor modelo
predicciones = mejor_modelo.predict(X)

# Evaluar el rendimiento del modelo
from sklearn.metrics import accuracy_score
precision = accuracy_score(y, predicciones)
print("Precisión del mejor modelo:", precision)

Es importante señalar que, por defecto, GridSearchCV utiliza la métrica de precisión para problemas de clasificación. Sin embargo, es posible especificar una métrica personalizada mediante el parámetro scoring. Por ejemplo, si deseamos optimizar el modelo utilizando la puntuación F1 micro, podemos ajustar el parámetro de la siguiente forma:

# Configurar GridSearchCV con métrica personalizada
grid_search = GridSearchCV(
    estimator=svc,
    param_grid=param_grid,
    scoring='f1_micro',
    cv=5,
    n_jobs=-1
)

La búsqueda en cuadrícula puede ser computacionalmente costosa, especialmente cuando el espacio de hiperparámetros es grande o el conjunto de datos es extenso. Para mitigar este problema, es recomendable:

  • Reducir el número de valores en cada hiperparámetro.
  • Limitar la búsqueda a los hiperparámetros más influyentes.
  • Utilizar técnicas que reduzcan el tiempo de cómputo, como Early Stopping si el modelo lo permite.

Cuando se trabaja con modelos complejos o conjuntos de datos grandes, es esencial equilibrar la exhaustividad de la búsqueda con los recursos computacionales disponibles. La búsqueda en cuadrícula es una herramienta fundamental en el proceso de selección de modelos, pero debe utilizarse con criterios bien definidos para maximizar su eficacia.

Búsqueda aleatoria (Random Search)

En la tarea de optimización de hiperparámetros, la búsqueda aleatoria (Random Search) es una técnica efectiva para encontrar combinaciones óptimas sin necesidad de probar exhaustivamente todas las posibilidades. A diferencia de la búsqueda en cuadrícula, Random Search selecciona aleatoriamente un conjunto de combinaciones de hiperparámetros dentro del espacio definido, lo que reduce significativamente el tiempo de cálculo.

Scikit-Learn ofrece la clase RandomizedSearchCV para facilitar este proceso. Esta herramienta permite explorar un espacio de hiperparámetros especificando distribuciones o listas de valores para cada uno, y evalúa cada combinación utilizando validación cruzada. Esto es especialmente útil cuando el número de hiperparámetros y sus posibles valores es grande.

A continuación, se presenta un ejemplo práctico utilizando RandomizedSearchCV para optimizar un modelo de bosque aleatorio (RandomForestClassifier). Emplearemos el conjunto de datos Iris para ilustrar el proceso:

import numpy as np
from scipy.stats import randint
from sklearn import datasets
from sklearn.model_selection import RandomizedSearchCV
from sklearn.ensemble import RandomForestClassifier

# Cargar el conjunto de datos Iris
iris = datasets.load_iris()
X, y = iris.data, iris.target

# Definir el modelo base
modelo = RandomForestClassifier()

# Definir el espacio de hiperparámetros a explorar
param_distribuciones = {
    'n_estimators': randint(50, 200),
    'max_depth': randint(5, 20),
    'min_samples_split': randint(2, 11),
    'min_samples_leaf': randint(1, 5),
    'bootstrap': [True, False]
}

# Configurar RandomizedSearchCV
busqueda_aleatoria = RandomizedSearchCV(
    estimator=modelo,
    param_distributions=param_distribuciones,
    n_iter=50,
    cv=5,
    random_state=42,
    n_jobs=-1
)

# Ejecutar la búsqueda aleatoria
busqueda_aleatoria.fit(X, y)

# Mostrar los mejores hiperparámetros encontrados
print("Mejores hiperparámetros:", busqueda_aleatoria.best_params_)

En este ejemplo, hemos definido distribuciones para los hiperparámetros clave del modelo. La función randint de scipy.stats crea distribuciones discretas uniformes, permitiendo que RandomizedSearchCV seleccione valores aleatorios dentro de los rangos especificados. El parámetro n_iter=50 indica que se evaluarán 50 combinaciones diferentes.

Una vez completada la búsqueda, es posible acceder al mejor modelo y evaluar su rendimiento:

# Obtener el mejor estimador
mejor_modelo = busqueda_aleatoria.best_estimator_

# Realizar predicciones con el mejor modelo
predicciones = mejor_modelo.predict(X)

# Evaluar la precisión del modelo
from sklearn.metrics import accuracy_score
precision = accuracy_score(y, predicciones)
print("Precisión del mejor modelo:", precision)

La búsqueda aleatoria ofrece varias ventajas respecto a la búsqueda en cuadrícula. Al no explorar todas las combinaciones posibles, es más eficiente en términos computacionales y puede encontrar configuraciones óptimas en menos tiempo. Además, es especialmente adecuada cuando se sospecha que solo algunos hiperparámetros influyen significativamente en el rendimiento.

Es posible personalizar la métrica de evaluación utilizando el parámetro scoring. Por ejemplo, si se desea optimizar el modelo según la puntuación F1 macro, se ajusta de la siguiente manera:

# Configurar RandomizedSearchCV con métrica personalizada
busqueda_aleatoria = RandomizedSearchCV(
    estimator=modelo,
    param_distributions=param_distribuciones,
    n_iter=50,
    scoring='f1_macro',
    cv=5,
    random_state=42,
    n_jobs=-1
)

La reproducibilidad de los resultados es crucial en entornos profesionales. Por ello, se recomienda establecer el parámetro random_state, tanto en RandomizedSearchCV como en los algoritmos que lo permitan. Esto asegura que los resultados sean consistentes en diferentes ejecuciones.

Para analizar detalladamente los resultados de la búsqueda, se puede acceder al atributo cv_results_ y convertirlo en un DataFrame para su exploración:

import pandas as pd

# Crear un DataFrame con los resultados
resultados = pd.DataFrame(busqueda_aleatoria.cv_results_)

# Ordenar las combinaciones por puntuación media
resultados_ordenados = resultados.sort_values('mean_test_score', ascending=False)

# Mostrar las primeras filas
print(resultados_ordenados.head())

Este análisis permite identificar patrones y comprender la influencia de cada hiperparámetro en el rendimiento del modelo. Además, facilita la toma de decisiones informadas para futuras optimizaciones.

Es importante considerar estrategias para reducir el tiempo de cómputo al utilizar Random Search:

  • Limitar el número de iteraciones (n_iter) en función de los recursos disponibles.
  • Enfocarse en los hiperparámetros más relevantes, descartando aquellos con menor impacto.
  • Utilizar validación cruzada con menos particiones o técnicas como ShuffleSplit para acelerar el proceso.

La flexibilidad de RandomizedSearchCV permite también incorporar distribuciones continuas para hiperparámetros, utilizando funciones como uniform de scipy.stats. Por ejemplo, para ajustar la tasa de aprendizaje (learning_rate) de un modelo GradientBoostingClassifier:

from scipy.stats import uniform
from sklearn.ensemble import GradientBoostingClassifier

# Definir el modelo base
modelo = GradientBoostingClassifier()

# Definir distribuciones para los hiperparámetros
param_distribuciones = {
    'n_estimators': randint(50, 200),
    'learning_rate': uniform(0.01, 0.2),
    'max_depth': randint(3, 10),
    'subsample': uniform(0.5, 0.5)
}

# Configurar RandomizedSearchCV
busqueda_aleatoria = RandomizedSearchCV(
    estimator=modelo,
    param_distributions=param_distribuciones,
    n_iter=100,
    cv=5,
    random_state=42,
    n_jobs=-1
)

# Ejecutar la búsqueda aleatoria
busqueda_aleatoria.fit(X, y)

En este caso, los hiperparámetros learning_rate y subsample se exploran dentro de distribuciones continuas, permitiendo una búsqueda más fina en el espacio de hiperparámetros.

La búsqueda aleatoria es una herramienta valiosa en el proceso de ajuste de hiperparámetros, combinando eficiencia y flexibilidad. Al aprovechar RandomizedSearchCV de Scikit-Learn, se puede mejorar significativamente el rendimiento de los modelos sin incurrir en costos computacionales elevados.

Validación cruzada anidada

La validación cruzada anidada es una técnica avanzada que combina la validación cruzada para estimar el rendimiento general del modelo y el ajuste de hiperparámetros de forma objetiva. Es especialmente útil para evitar el sobreajuste durante el proceso de selección de modelos y proporciona una estimación más realista de la capacidad de generalización.

En los procesos estándar de validación, al ajustar hiperparámetros con métodos como Grid Search o Random Search, existe el riesgo de que el modelo se adapte demasiado a los datos de validación, influyendo negativamente en la estimación del rendimiento. La validación cruzada anidada resuelve este problema al utilizar dos niveles de validación cruzada:

  • Un bucle externo para evaluar el rendimiento del modelo.
  • Un bucle interno para ajustar los hiperparámetros.

Este enfoque garantiza que la evaluación del modelo se realice en datos completamente independientes de aquellos utilizados para el ajuste de hiperparámetros.

A continuación, se presenta un ejemplo práctico utilizando Scikit-Learn para implementar la validación cruzada anidada con un modelo de Máquinas de Vectores de Soporte (SVM):

import numpy as np
from sklearn import datasets
from sklearn.svm import SVC
from sklearn.model_selection import GridSearchCV, cross_val_score, KFold

# Cargar el conjunto de datos Iris
iris = datasets.load_iris()
X, y = iris.data, iris.target

# Definir el rango de hiperparámetros para Grid Search
param_grid = {
    'C': [0.1, 1, 10],
    'kernel': ['linear', 'rbf']
}

# Configurar el modelo base
modelo = SVC()

# Configurar GridSearchCV para el bucle interno
grid_search = GridSearchCV(
    estimator=modelo,
    param_grid=param_grid,
    cv=5,
    n_jobs=-1
)

# Configurar el bucle externo de validación cruzada
cv_externo = KFold(n_splits=5, shuffle=True, random_state=42)

# Ejecutar la validación cruzada anidada
puntuaciones = cross_val_score(
    estimator=grid_search,
    X=X,
    y=y,
    cv=cv_externo,
    n_jobs=-1
)

# Mostrar las puntuaciones obtenidas en cada iteración
print("Puntuaciones en cada pliegue:", puntuaciones)
print("Precisión media:", np.mean(puntuaciones))
print("Desviación estándar:", np.std(puntuaciones))

En este código, cross_val_score se utiliza con grid_search como estimador. En cada partición del bucle externo (cv_externo), se realiza una búsqueda de hiperparámetros mediante GridSearchCV, que implementa su propia validación cruzada interna. De esta manera, los hiperparámetros se ajustan exclusivamente en los datos de entrenamiento de cada partición, y la evaluación se realiza en los datos de prueba correspondientes.

Es importante destacar que la validación cruzada anidada proporciona una estimación del rendimiento más conservadora y confiable. Esto es especialmente relevante cuando se comparan diferentes modelos o algoritmos, ya que minimiza el riesgo de selecciones sesgadas.

Para ilustrar la diferencia entre una validación cruzada simple y una anidada, consideremos un ejemplo donde se comparan ambos enfoques:

from sklearn.model_selection import cross_val_score, KFold

# Validación cruzada simple sin anidamiento
cv_simple = KFold(n_splits=5, shuffle=True, random_state=42)
puntuaciones_simple = cross_val_score(
    estimator=grid_search,
    X=X,
    y=y,
    cv=cv_simple,
    n_jobs=-1
)

print("Precisión media (validación cruzada simple):", np.mean(puntuaciones_simple))

# Validación cruzada anidada
cv_externo = KFold(n_splits=5, shuffle=True, random_state=42)
puntuaciones_anidada = cross_val_score(
    estimator=grid_search,
    X=X,
    y=y,
    cv=cv_externo,
    n_jobs=-1
)

print("Precisión media (validación cruzada anidada):", np.mean(puntuaciones_anidada))

En este caso, ambas puntuaciones pueden diferir, evidenciando el impacto del sobreajuste durante el ajuste de hiperparámetros. La validación cruzada anidada suele producir una estimación más realista del rendimiento en datos no vistos.

Además, es posible utilizar RandomizedSearchCV dentro de la validación cruzada anidada. El proceso es similar, simplemente sustituyendo GridSearchCV por RandomizedSearchCV:

from sklearn.model_selection import RandomizedSearchCV
from scipy.stats import loguniform

# Definir las distribuciones de hiperparámetros para Random Search
param_distribuciones = {
    'C': loguniform(1e-3, 1e3),
    'kernel': ['linear', 'rbf']
}

# Configurar RandomizedSearchCV
random_search = RandomizedSearchCV(
    estimator=modelo,
    param_distributions=param_distribuciones,
    n_iter=20,
    cv=5,
    n_jobs=-1,
    random_state=42
)

# Ejecutar la validación cruzada anidada con Random Search
puntuaciones = cross_val_score(
    estimator=random_search,
    X=X,
    y=y,
    cv=cv_externo,
    n_jobs=-1
)

print("Precisión media (Random Search):", np.mean(puntuaciones))

La validación cruzada anidada es especialmente útil en situaciones con conjuntos de datos limitados, donde es crucial utilizar los datos de manera eficiente sin comprometer la estimación del rendimiento. No obstante, este método puede ser computacionalmente costoso debido al número de modelos entrenados en los bucles interno y externo.

Para mejorar la eficiencia, se pueden considerar las siguientes estrategias:

  • Reducir el número de particiones en los bucles interno y externo.
  • Limitar el espacio de búsqueda de hiperparámetros.
  • Utilizar técnicas de muestreo más rápidas o modelos más simples.

Además, Scikit-Learn permite personalizar las métricas de evaluación en ambos niveles de validación. Por ejemplo, para utilizar la puntuación F1 en un problema de clasificación binaria:

from sklearn.metrics import make_scorer, f1_score

# Definir un scorer personalizado
f1_scorer = make_scorer(f1_score, average='binary')

# Configurar GridSearchCV con el scorer
grid_search = GridSearchCV(
    estimator=modelo,
    param_grid=param_grid,
    scoring=f1_scorer,
    cv=5,
    n_jobs=-1
)

# Ejecutar la validación cruzada anidada con la métrica personalizada
puntuaciones = cross_val_score(
    estimator=grid_search,
    X=X,
    y=y,
    scoring=f1_scorer,
    cv=cv_externo,
    n_jobs=-1
)

Es fundamental asegurarse de que las particiones del bucle externo sean independientes y representativas. Para ello, se pueden utilizar estrategias de validación cruzada como StratifiedKFold en problemas de clasificación con clases desbalanceadas.

La validación cruzada anidada es una técnica poderosa para la selección de modelos y la estimación precisa de su rendimiento. Al separar claramente las etapas de ajuste y evaluación, proporciona una medida más fiable de cómo el modelo generalizará a nuevos datos.

Curvas de validación y aprendizaje

Las curvas de validación y aprendizaje son herramientas esenciales para evaluar el rendimiento y el comportamiento de los modelos de aprendizaje automático. Estas curvas permiten entender cómo varía la precisión o el error del modelo en función de diferentes factores, como el tamaño del conjunto de entrenamiento o los valores de los hiperparámetros. Su uso es crucial para detectar problemas de sobreajuste o subajuste y mejorar la generalización del modelo.

Curvas de aprendizaje

Las curvas de aprendizaje muestran la evolución del rendimiento del modelo en función del tamaño del conjunto de entrenamiento. Al entrenar el modelo con cantidades crecientes de datos, se observa cómo varía la puntuación tanto en el conjunto de entrenamiento como en el de validación. Esto ayuda a determinar si el modelo se beneficia de más datos o si alcanza una meseta en su rendimiento.

Para ilustrar su uso en Scikit-Learn, consideremos un ejemplo práctico con un clasificador Random Forest aplicado al conjunto de datos de dígitos escritos a mano.

import numpy as np
from sklearn.datasets import load_digits
from sklearn.model_selection import learning_curve
from sklearn.ensemble import RandomForestClassifier
import matplotlib.pyplot as plt

# Cargar el conjunto de datos
X, y = load_digits(return_X_y=True)

# Definir el modelo
modelo = RandomForestClassifier(random_state=42)

# Obtener la curva de aprendizaje
train_sizes, train_scores, test_scores = learning_curve(
    estimator=modelo,
    X=X,
    y=y,
    cv=5,
    train_sizes=np.linspace(0.1, 1.0, 10),
    n_jobs=-1
)

# Calcular la media y desviación estándar de las puntuaciones
train_scores_mean = np.mean(train_scores, axis=1)
train_scores_std = np.std(train_scores, axis=1)
test_scores_mean = np.mean(test_scores, axis=1)
test_scores_std = np.std(test_scores, axis=1)

# Graficar la curva de aprendizaje
plt.figure(figsize=(8, 6))
plt.plot(train_sizes, train_scores_mean, label='Precisión en entrenamiento')
plt.fill_between(train_sizes,
                 train_scores_mean - train_scores_std,
                 train_scores_mean + train_scores_std, alpha=0.15)
plt.plot(train_sizes, test_scores_mean, label='Precisión en validación')
plt.fill_between(train_sizes,
                 test_scores_mean - test_scores_std,
                 test_scores_mean + test_scores_std, alpha=0.15)
plt.title('Curva de aprendizaje del modelo Random Forest')
plt.xlabel('Tamaño del conjunto de entrenamiento')
plt.ylabel('Precisión')
plt.legend()
plt.grid(True)
plt.show()

En este código, la función learning_curve calcula las puntuaciones del modelo para diferentes tamaños del conjunto de entrenamiento utilizando validación cruzada. Las curvas resultantes permiten visualizar si el modelo mejora al aumentar los datos o si su rendimiento se estabiliza.

Interpretación de la curva de aprendizaje:

  • Si la precisión en entrenamiento es alta y en validación es baja, el modelo podría estar sobreajustando.
  • Si la precisión en ambos conjuntos es baja, el modelo podría estar subajustando.
  • Si la precisión en validación continúa mejorando al aumentar los datos, es posible que se beneficie de más datos de entrenamiento.

Curvas de validación

Las curvas de validación evalúan el rendimiento del modelo al variar los valores de un hiperparámetro específico. Son útiles para identificar el valor óptimo de un hiperparámetro que maximiza la precisión en el conjunto de validación. A diferencia de las curvas de aprendizaje, aquí el tamaño del conjunto de entrenamiento permanece constante.

Como ejemplo, analizaremos cómo afecta el parámetro C en un clasificador Support Vector Machine (SVM).

import numpy as np
from sklearn.datasets import load_digits
from sklearn.model_selection import validation_curve
from sklearn.svm import SVC
import matplotlib.pyplot as plt

# Cargar el conjunto de datos
X, y = load_digits(return_X_y=True)

# Definir los valores del hiperparámetro C a evaluar
param_range = np.logspace(-4, 4, 10)

# Obtener la curva de validación
train_scores, test_scores = validation_curve(
    estimator=SVC(),
    X=X,
    y=y,
    param_name='C',
    param_range=param_range,
    cv=5,
    scoring='accuracy',
    n_jobs=-1
)

# Calcular la media y desviación estándar
train_scores_mean = np.mean(train_scores, axis=1)
train_scores_std = np.std(train_scores, axis=1)
test_scores_mean = np.mean(test_scores, axis=1)
test_scores_std = np.std(test_scores, axis=1)

# Graficar la curva de validación
plt.figure(figsize=(8, 6))
plt.semilogx(param_range, train_scores_mean, label='Precisión en entrenamiento')
plt.fill_between(param_range,
                 train_scores_mean - train_scores_std,
                 train_scores_mean + train_scores_std, alpha=0.15)
plt.semilogx(param_range, test_scores_mean, label='Precisión en validación')
plt.fill_between(param_range,
                 test_scores_mean - test_scores_std,
                 test_scores_mean + test_scores_std, alpha=0.15)
plt.title('Curva de validación para SVM variando C')
plt.xlabel('Valor de C')
plt.ylabel('Precisión')
plt.legend()
plt.grid(True)
plt.show()

En este script, validation_curve evalúa el modelo para distintos valores de C. La gráfica resultante muestra cómo varía la precisión al modificar este hiperparámetro, ayudando a identificar el valor que maximiza la generalización del modelo.

Interpretación de la curva de validación:

  • Un aumento en la precisión en entrenamiento pero no en validación puede indicar sobreajuste.
  • Si la precisión en ambos conjuntos es baja, el modelo puede estar subajustando.
  • El punto donde la precisión en validación es máxima sugiere el valor óptimo del hiperparámetro.

Uso combinado para optimización

Combinar las curvas de aprendizaje y validación proporciona una visión completa del rendimiento del modelo y de cómo mejorar su capacidad predictiva.

Ejemplo con regresión:

Supongamos que utilizamos Ridge Regression y queremos explorar el efecto del parámetro de regularización alpha.

import numpy as np
from sklearn.datasets import fetch_california_housing
from sklearn.model_selection import validation_curve
from sklearn.linear_model import Ridge
import matplotlib.pyplot as plt

# Cargar el conjunto de datos
X, y = fetch_california_housing(return_X_y=True)

# Definir los valores de alpha a evaluar
param_range = np.logspace(-3, 3, 10)

# Obtener la curva de validación
train_scores, test_scores = validation_curve(
    estimator=Ridge(),
    X=X,
    y=y,
    param_name='alpha',
    param_range=param_range,
    cv=5,
    scoring='neg_mean_squared_error',
    n_jobs=-1
)

# Calcular la media y desviación estándar y cambiar el signo
train_scores_mean = -np.mean(train_scores, axis=1)
train_scores_std = np.std(train_scores, axis=1)
test_scores_mean = -np.mean(test_scores, axis=1)
test_scores_std = np.std(test_scores, axis=1)

# Graficar la curva de validación
plt.figure(figsize=(8, 6))
plt.semilogx(param_range, train_scores_mean, label='Error en entrenamiento')
plt.fill_between(param_range,
                 train_scores_mean - train_scores_std,
                 train_scores_mean + train_scores_std, alpha=0.15)
plt.semilogx(param_range, test_scores_mean, label='Error en validación')
plt.fill_between(param_range,
                 test_scores_mean - test_scores_std,
                 test_scores_mean + test_scores_std, alpha=0.15)
plt.title('Curva de validación para Ridge Regression variando alpha')
plt.xlabel('Valor de alpha')
plt.ylabel('Error cuadrático medio')
plt.legend()
plt.grid(True)
plt.show()

En este caso, estamos minimizando el error cuadrático medio. La curva nos permite identificar el valor de alpha que equilibra el error en entrenamiento y validación, mejorando la generalización.

Consideraciones prácticas

  • Las curvas de aprendizaje ayudan a decidir si es necesario más datos o ajustar la complejidad del modelo.
  • Las curvas de validación son útiles para afinar hiperparámetros individuales.
  • Es esencial utilizar un número adecuado de particiones en la validación cruzada para obtener resultados confiables.
  • Añadir barras de error o áreas sombreadas que representen la desviación estándar aporta información sobre la variabilidad de las puntuaciones.

Aplicación en pipelines

Al utilizar pipelines que combinan preprocesamiento y modelado, es importante aplicar las curvas sobre el pipeline completo para reflejar el rendimiento real.

from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.neighbors import KNeighborsClassifier

# Crear un pipeline con estandarización y KNN
pipeline = make_pipeline(StandardScaler(), KNeighborsClassifier(), memory= None)

# Definir los valores de n_neighbors a evaluar
param_range = range(1, 31)

# Obtener la curva de validación
train_scores, test_scores = validation_curve(
    estimator=pipeline,
    X=X,
    y=y,
    param_name='kneighborsclassifier__n_neighbors',
    param_range=param_range,
    cv=5,
    scoring='accuracy',
    n_jobs=-1
)

# Calcular la media de las puntuaciones
train_scores_mean = np.mean(train_scores, axis=1)
test_scores_mean = np.mean(test_scores, axis=1)

# Graficar la curva de validación
plt.figure(figsize=(8, 6))
plt.plot(param_range, train_scores_mean, label='Precisión en entrenamiento')
plt.plot(param_range, test_scores_mean, label='Precisión en validación')
plt.title('Curva de validación para KNN variando n_neighbors')
plt.xlabel('Número de vecinos')
plt.ylabel('Precisión')
plt.legend()
plt.grid(True)
plt.show()

En este ejemplo, hemos utilizado el pipeline para evaluar el impacto de n_neighbors en el rendimiento del modelo, asegurando que el preprocesamiento se aplique de forma consistente.

Ventajas y limitaciones

Ventajas:

  • Facilitan el diagnóstico de problemas de sobreajuste y subajuste.
  • Permiten identificar si se necesita más datos o ajustar hiperparámetros.
  • Ayudan a visualizar el impacto de las decisiones de modelado.

Limitaciones:

  • Pueden ser computacionalmente costosas en conjuntos de datos grandes.
  • La interpretación puede complicarse con modelos y hiperparámetros complejos.
  • No sustituyen otras técnicas de validación y deben utilizarse como complemento.

Es recomendable utilizar las curvas de validación y aprendizaje en conjunto con otras estrategias, como la búsqueda en cuadrícula o la validación cruzada anidada, para obtener una visión completa y mejorar la eficacia del proceso de modelado.

Herramientas de selección de modelos en Scikit-Learn

El módulo model_selection de Scikit-Learn proporciona una variedad de herramientas esenciales para la selección de modelos y el ajuste de hiperparámetros de manera más eficiente y robusta. Entre estas herramientas destacan las estrategias avanzadas de búsqueda como HalvingGridSearchCV y HalvingRandomSearchCV, que implementan algoritmos de Successive Halving para optimizar el proceso de búsqueda.

HalvingGridSearchCV y HalvingRandomSearchCV

Las clases HalvingGridSearchCV y HalvingRandomSearchCV son variantes más eficientes de GridSearchCV y RandomizedSearchCV, respectivamente. Utilizan el método de Successive Halving, que asigna recursos computacionales a un conjunto amplio de configuraciones de hiperparámetros y, progresivamente, enfoca estos recursos en las configuraciones más prometedoras.

Funcionamiento del método Successive Halving

El algoritmo comienza evaluando todas las combinaciones de hiperparámetros con un recurso mínimo (por ejemplo, pocas iteraciones o menos muestras). Después de cada iteración, elimina una fracción de las configuraciones menos prometedoras, asignando más recursos a las restantes. Este proceso continúa hasta que se alcanza el máximo de recursos, identificando así la mejor combinación de hiperparámetros de forma más eficiente.

Ejemplo práctico con HalvingGridSearchCV

A continuación, se muestra un ejemplo de cómo utilizar HalvingGridSearchCV para optimizar los hiperparámetros de un clasificador de bosque aleatorio:

import numpy as np
from sklearn.datasets import load_wine
from sklearn.ensemble import RandomForestClassifier
from sklearn.experimental import enable_halving_search_cv
from sklearn.model_selection import HalvingGridSearchCV

# Cargar el conjunto de datos Wine
X, y = load_wine(return_X_y=True)

# Definir el modelo base
modelo = RandomForestClassifier(random_state=42)

# Definir el espacio de hiperparámetros
param_grid = {
    'n_estimators': [50, 100, 200],
    'max_depth': [None, 10, 20, 30],
    'min_samples_split': [2, 5, 10]
}

# Configurar HalvingGridSearchCV
halving_grid_search = HalvingGridSearchCV(
    estimator=modelo,
    param_grid=param_grid,
    factor=2,
    scoring='accuracy',
    cv=5,
    n_jobs=-1,
    random_state=42
)

# Ejecutar la búsqueda
halving_grid_search.fit(X, y)

# Mostrar los mejores hiperparámetros encontrados
print("Mejores hiperparámetros:", halving_grid_search.best_params_)
print("Mejor puntuación de validación:", halving_grid_search.best_score_)

En este ejemplo, HalvingGridSearchCV explora eficientemente el espacio de hiperparámetros definido en param_grid. El parámetro factor=2 indica que en cada iteración el número de configuraciones se reduce a la mitad, asignando más recursos a las configuraciones superiores. El uso de n_jobs=-1 permite paralelizar el proceso, aprovechando todos los núcleos disponibles.

Ventajas de HalvingGridSearchCV

  • Eficiencia computacional: Reduce el tiempo de búsqueda al descartar rápidamente las configuraciones menos prometedoras.
  • Uso óptimo de recursos: Optimiza la asignación de recursos a configuraciones con mayor rendimiento.
  • Facilidad de implementación: Interfaz similar a GridSearchCV, facilitando su adopción en proyectos existentes.

Ejemplo práctico con HalvingRandomSearchCV

HalvingRandomSearchCV combina el enfoque aleatorio de RandomizedSearchCV con el método de Successive Halving. A continuación, se presenta un ejemplo utilizando un clasificador SVM:

from scipy.stats import uniform
from sklearn.svm import SVC
from sklearn.model_selection import HalvingRandomSearchCV

# Definir el modelo base
modelo = SVC(random_state=42)

# Definir las distribuciones de hiperparámetros
param_distributions = {
    'C': uniform(0.1, 10),
    'kernel': ['linear', 'rbf', 'poly'],
    'gamma': ['scale', 'auto']
}

# Configurar HalvingRandomSearchCV
halving_random_search = HalvingRandomSearchCV(
    estimator=modelo,
    param_distributions=param_distributions,
    factor=3,
    scoring='accuracy',
    cv=5,
    n_jobs=-1,
    random_state=42
)

# Ejecutar la búsqueda
halving_random_search.fit(X, y)

# Mostrar los mejores hiperparámetros encontrados
print("Mejores hiperparámetros:", halving_random_search.best_params_)
print("Mejor puntuación de validación:", halving_random_search.best_score_)

En este caso, HalvingRandomSearchCV selecciona aleatoriamente combinaciones de hiperparámetros de acuerdo con las distribuciones especificadas en param_distributions. El parámetro factor=3 reduce el número de configuraciones en un tercio en cada iteración.

Uso de diferentes estrategias de validación cruzada

Las herramientas de selección de modelos en Scikit-Learn permiten personalizar las estrategias de validación cruzada mediante el parámetro cv. Es posible utilizar diferentes divisiones, como StratifiedKFold, GroupKFold o TimeSeriesSplit, para adaptar el proceso de evaluación a las características de los datos.

Ejemplo con TimeSeriesSplit

Para datos de series temporales donde el orden es relevante, se puede emplear TimeSeriesSplit:

from sklearn.model_selection import TimeSeriesSplit

# Configurar TimeSeriesSplit
tscv = TimeSeriesSplit(n_splits=5)

# Configurar HalvingGridSearchCV con TimeSeriesSplit
halving_grid_search = HalvingGridSearchCV(
    estimator=modelo,
    param_grid=param_grid,
    scoring='accuracy',
    cv=tscv,
    n_jobs=-1
)

# Ejecutar la búsqueda en series temporales
halving_grid_search.fit(X, y)

Utilizar la estrategia apropiada de validación es fundamental para obtener estimaciones fiables del rendimiento del modelo y tomar decisiones informadas durante la selección de modelos.

Evaluación con múltiples métricas

Scikit-Learn permite optimizar y evaluar modelos utilizando múltiples métricas simultáneamente. Esto es posible mediante el parámetro scoring, al que se le puede pasar una lista o un diccionario de métricas.

Ejemplo con múltiples métricas

from sklearn.metrics import make_scorer, f1_score, precision_score, recall_score

# Definir las métricas de evaluación
metricas = {
    'accuracy': 'accuracy',
    'precision': make_scorer(precision_score, average='macro'),
    'recall': make_scorer(recall_score, average='macro'),
    'f1': make_scorer(f1_score, average='macro')
}

# Configurar HalvingGridSearchCV con múltiples métricas
halving_grid_search = HalvingGridSearchCV(
    estimator=modelo,
    param_grid=param_grid,
    scoring='f1_macro',
    refit=True,
    cv=5,
    n_jobs=-1
)

# Ejecutar la búsqueda
halving_grid_search.fit(X, y)

# Mostrar las mejores puntuaciones
print("Mejores puntuaciones:", halving_grid_search.best_score_)
print("Mejores hiperparámetros según F1:", halving_grid_search.best_params_)

En este ejemplo, se evalúa el modelo utilizando métricas como precisión, exhaustividad y puntuación F1. El parámetro scoring='f1_macro' indica que se seleccionará el modelo que maximice la puntuación F1 y se reajustará utilizando todos los datos de entrenamiento.

Uso de cross_validate para obtener información detallada

La función cross_validate permite evaluar un modelo utilizando validación cruzada y obtener diversas métricas, incluyendo tiempos de ajuste y predicción.

Ejemplo de cross_validate

from sklearn.model_selection import cross_validate

# Evaluar el modelo con cross_validate
resultados = cross_validate(
    estimator=modelo,
    X=X,
    y=y,
    cv=5,
    scoring=metricas,
    return_train_score=True,
    n_jobs=-1
)

# Convertir los resultados en un DataFrame
import pandas as pd
df_resultados = pd.DataFrame(resultados)

# Mostrar las medias de las métricas
print(df_resultados.mean())

Con cross_validate, es posible analizar en detalle el rendimiento del modelo, facilitando la identificación de posibles problemas como el sobreajuste o cuellos de botella computacionales.

Uso de cross_val_predict para obtener predicciones

La función cross_val_predict genera predicciones obtenidas mediante validación cruzada, útil para análisis adicionales como la creación de curvas ROC o matrices de confusión.

Ejemplo de cross_val_predict

from sklearn.model_selection import cross_val_predict
from sklearn.metrics import confusion_matrix

# Obtener las predicciones de validación cruzada
predicciones = cross_val_predict(
    estimator=modelo,
    X=X,
    y=y,
    cv=5,
    n_jobs=-1
)

# Calcular la matriz de confusión
matriz_confusion = confusion_matrix(y, predicciones)
print("Matriz de confusión:\n", matriz_confusion)

Estas predicciones reflejan cómo el modelo generaliza a datos no vistos, proporcionando una estimación más realista de su rendimiento.

Personalización de funciones de valoración

Scikit-Learn permite definir funciones de valoración personalizadas para evaluar y optimizar modelos según criterios específicos.

Ejemplo de función de valoración personalizada

from sklearn.metrics import make_scorer

# Definir una función de valoración personalizada
def puntuacion_personalizada(y_true, y_pred):
    # Implementar lógica específica
    return mi_metrica

# Crear el scorer personalizado
mi_scorer = make_scorer(puntuacion_personalizada, greater_is_better=True)

# Configurar GridSearchCV con el scorer personalizado
grid_search = HalvingGridSearchCV(
    estimator=modelo,
    param_grid=param_grid,
    scoring=mi_scorer,
    cv=5,
    n_jobs=-1
)

Esta flexibilidad permite adaptar el proceso de selección de modelos a los objetivos y restricciones del problema en cuestión.

Consideraciones finales

Las herramientas de selección de modelos en Scikit-Learn ofrecen una amplia gama de funcionalidades para optimizar y evaluar modelos de manera eficiente y robusta. Al aprovechar técnicas avanzadas como HalvingGridSearchCV, personalizar estrategias de validación y utilizar múltiples métricas, es posible mejorar significativamente el rendimiento de los modelos y garantizar su capacidad de generalización.

Es esencial comprender las características y limitaciones de cada herramienta para aplicarlas adecuadamente en diferentes contextos y tipos de datos. La combinación de estas herramientas con buenas prácticas de ingeniería de características y preprocesamiento conduce a soluciones más efectivas y confiables en proyectos de aprendizaje automático.

Aprende ScikitLearn GRATIS online

Ejercicios de esta lección Ajuste de hiperparámetros

Evalúa tus conocimientos de esta lección Ajuste de hiperparámetros con nuestros retos de programación de tipo Test, Puzzle, Código y Proyecto con VSCode, guiados por IA.

Todas las lecciones de ScikitLearn

Accede a todas las lecciones de ScikitLearn y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.

Aprendizaje Automático

scikit-learn

Introducción Y Entorno

Introducción E Instalación

scikit-learn

Introducción Y Entorno

Introducción Al Preprocesamiento De Datos

scikit-learn

Preprocesamiento De Datos

Identificación Y Tratamiento De Valores Faltantes

scikit-learn

Preprocesamiento De Datos

Escalado De Datos

scikit-learn

Preprocesamiento De Datos

Normalización De Datos

scikit-learn

Preprocesamiento De Datos

Codificación De Variables Categóricas

scikit-learn

Preprocesamiento De Datos

Ingeniería De Características

scikit-learn

Preprocesamiento De Datos

Selección De Características

scikit-learn

Preprocesamiento De Datos

Extracción De Características

scikit-learn

Preprocesamiento De Datos

Particionamiento De Datos

scikit-learn

Preprocesamiento De Datos

Preprocesamiento De Datos Desbalanceados

scikit-learn

Preprocesamiento De Datos

Introducción A La Regresión

scikit-learn

Regresión

Regresión Lineal

scikit-learn

Regresión

Regresión Knn Kneighborsregressor

scikit-learn

Regresión

Regresión Svm Con Svr

scikit-learn

Regresión

Regresión Con Árboles Decisiontreeregressor

scikit-learn

Regresión

Regresión Con Algoritmos De Conjunto

scikit-learn

Regresión

Introducción A La Clasificación

scikit-learn

Clasificación

Clasificación Con Regresión Logística

scikit-learn

Clasificación

Clasificación Knn Kneighborsclassifier

scikit-learn

Clasificación

Clasificación Svm Con Svc

scikit-learn

Clasificación

Clasificación Con Árboles Decisiontreeclassifier

scikit-learn

Clasificación

Clasificación Con Algoritmos De Conjunto

scikit-learn

Clasificación

Reducción De La Dimensionalidad Con Pca

scikit-learn

Aprendizaje No Supervisado

Clustering Con Kmeans

scikit-learn

Aprendizaje No Supervisado

Clustering Jerárquico

scikit-learn

Aprendizaje No Supervisado

Clustering De Densidad Con Dbscan

scikit-learn

Aprendizaje No Supervisado

Preprocesamiento De Textos Para Nlp

scikit-learn

Nlp

Representación De Texto Y Extracción De Características

scikit-learn

Nlp

Clasificación De Texto Con Scikit Learn

scikit-learn

Nlp

Análisis De Sentimiento

scikit-learn

Nlp

Técnicas Avanzadas De Extracción De Características

scikit-learn

Nlp

Introducción Al Análisis De Series Temporales

scikit-learn

Series Temporales

Preprocesamiento De Datos De Series Temporales

scikit-learn

Series Temporales

Ingeniería De Características Para Series Temporales

scikit-learn

Series Temporales

Transformación Y Escalado De Series Temporales

scikit-learn

Series Temporales

Validación Y Evaluación De Modelos En Series Temporales

scikit-learn

Series Temporales

Validación Y Evaluación De Modelos

scikit-learn

Validación De Modelos

Técnicas De Validación Cruzada

scikit-learn

Validación De Modelos

Métricas De Regresión

scikit-learn

Validación De Modelos

Métricas De Clasificación

scikit-learn

Validación De Modelos

Ajuste De Hiperparámetros

scikit-learn

Validación De Modelos

Introducción A Pipelines

scikit-learn

Pipelines Y Despliegue

Creación De Pipelines Básicos

scikit-learn

Pipelines Y Despliegue

Preprocesamiento De Datos Con Pipelines

scikit-learn

Pipelines Y Despliegue

Pipelines Y Validación Cruzada

scikit-learn

Pipelines Y Despliegue

Pipelines Con Columntransformer

scikit-learn

Pipelines Y Despliegue

Exportar E Importar Pipelines

scikit-learn

Pipelines Y Despliegue

Accede GRATIS a ScikitLearn y certifícate

Objetivos de aprendizaje de esta lección

  • Entender el concepto de búsqueda en cuadrícula y su aplicación práctica.
  • Utilizar el módulo GridSearchCV de Scikit-Learn para la selección de hiperparámetros.
  • Implementar validación cruzada para robustecer la evaluación del modelo.
  • Identificar buenas prácticas de optimización para mejorar la eficiencia computacional.