scikit-learn

ScikitLearn

Tutorial ScikitLearn: Pipelines y Validación Cruzada

Domina la integración de Pipelines en Scikit-Learn con `cross_val_score` para evaluar modelos de aprendizaje automático con precisión y evitar fugas de datos.

Aprende ScikitLearn GRATIS y certifícate

Integración con cross_val_score

La integración de Pipelines con la función cross_val_score de Scikit-Learn permite evaluar modelos de manera eficiente y estructurada. Al combinar ambos, se asegura que todas las etapas, desde el preprocesamiento hasta la predicción, se validen correctamente sin causar fugas de datos.

Por ejemplo, supongamos que estamos trabajando con el conjunto de datos de dígitos escrito a mano:

from sklearn.datasets import load_digits
from sklearn.pipeline import Pipeline
from sklearn.model_selection import cross_val_score
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression

# Cargar los datos
digits = load_digits()
X, y = digits.data, digits.target

# Crear el Pipeline con memoria
pipeline = Pipeline([
    ('escalador', StandardScaler()),
    ('clasificador', LogisticRegression())
], memory='cache_directory')

# Evaluar el modelo usando validación cruzada
puntuaciones = cross_val_score(pipeline, X, y, cv=5)

print("Puntuaciones de validación cruzada:", puntuaciones)
print("Precisión media:", puntuaciones.mean())

En este ejemplo, se crea un Pipeline que primero estandariza las características con StandardScaler y luego aplica un clasificador de regresión logística. El parámetro memory almacena en caché los transformadores, optimizando la ejecución. La función cross_val_score realiza una validación cruzada con 5 particiones, proporcionando una estimación fiable del rendimiento del modelo.

Al utilizar cross_val_score con un Pipeline, garantizamos que el escalado y cualquier otra transformación se ajusten únicamente con los datos de entrenamiento en cada pliegue. Esto evita el sobreajuste y asegura una evaluación más realista.

También es posible personalizar la validación cruzada. Por ejemplo, para utilizar una validación cruzada estratificada:

from sklearn.model_selection import StratifiedKFold

# Definir la estrategia de validación cruzada
cv = StratifiedKFold(n_splits=5)

# Evaluar el modelo con la estrategia personalizada
puntuaciones = cross_val_score(pipeline, X, y, cv=cv)

print("Puntuaciones de validación cruzada:", puntuaciones)
print("Precisión media:", puntuaciones.mean())

La estrategia StratifiedKFold mantiene la proporción de clases en cada partición, lo cual es crucial en problemas con clases desequilibradas.

Además, los Pipelines facilitan la incorporación de múltiples etapas de preprocesamiento. Por ejemplo, para añadir una selección de características:

from sklearn.feature_selection import SelectKBest, chi2
from sklearn.preprocessing import MinMaxScaler

# Crear un Pipeline con selección de características
pipeline = Pipeline([
    ('escalador', MinMaxScaler()), 
    ('seleccion', SelectKBest(score_func=chi2, k=30)),  
    ('clasificador', LogisticRegression(max_iter=1000, random_state=42)) 
], memory='cache_directory')

# Evaluar el modelo
puntuaciones = cross_val_score(pipeline, X, y, cv=5)

print("Puntuaciones de validación cruzada:", puntuaciones)
print("Precisión media:", puntuaciones.mean())

Aquí se utiliza SelectKBest para seleccionar las 30 mejores características basadas en la prueba chi-cuadrado, antes de aplicar el clasificador. La integración con cross_val_score permite evaluar todo el flujo de trabajo de manera cohesiva.

Integrar Pipelines con cross_val_score no solo simplifica el código, sino que también mejora la reproducibilidad y la integridad del proceso de validación, aspectos fundamentales en proyectos de aprendizaje automático.

Uso de GridSearchCV y RandomizedSearchCV con Pipelines

La combinación de Pipelines con herramientas de búsqueda de hiperparámetros como GridSearchCV y RandomizedSearchCV en Scikit-Learn simplifica el proceso de optimización de modelos. Al integrar estas técnicas, se pueden ajustar los hiperparámetros de los pasos individuales del Pipeline de forma conjunta, facilitando la experimentación y mejorando el rendimiento del modelo.

Por ejemplo, supongamos que queremos optimizar un modelo de clasificación que incluye una etapa de preprocesamiento y un clasificador. Podemos utilizar un Pipeline para encapsular estas etapas y GridSearchCV para encontrar la mejor combinación de hiperparámetros:

from sklearn.datasets import fetch_openml
from sklearn.model_selection import GridSearchCV
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC

# Cargar el conjunto de datos MNIST
X, y = fetch_openml('mnist_784', version=1, return_X_y=True)

# Definir el Pipeline con memoria
pipeline = Pipeline([
    ('escalador', StandardScaler()),
    ('clasificador', SVC())
], memory='memory_cache')

# Definir el espacio de hiperparámetros a explorar
parametros = {
    'clasificador__C': [0.1, 1, 10],
    'clasificador__gamma': [1, 0.1, 0.01],
    'clasificador__kernel': ['rbf', 'linear']
}

# Configurar GridSearchCV
grid_search = GridSearchCV(pipeline, parametros, cv=3)

# Ejecutar la búsqueda de hiperparámetros
grid_search.fit(X, y)

# Mostrar los mejores parámetros encontrados
print("Mejores parámetros:", grid_search.best_params_)
print("Mejor puntuación:", grid_search.best_score_)

En este ejemplo, el Pipeline consta de un escalador StandardScaler y un clasificador SVM (SVC). El diccionario parametros especifica los hiperparámetros a optimizar, utilizando la notación nombre_etapa__nombre_parametro. Al ajustar el Pipeline con GridSearchCV, se exploran todas las combinaciones posibles de hiperparámetros definidos.

Es importante destacar que al usar Pipelines con GridSearchCV, se evitan fugas de datos, ya que cada combinación de hiperparámetros se evalúa siguiendo el flujo completo del Pipeline, garantizando que las transformaciones se apliquen correctamente en cada pliegue de validación cruzada.

Si el espacio de hiperparámetros es muy grande y el tiempo de cómputo es una limitación, RandomizedSearchCV ofrece una alternativa eficiente al realizar una búsqueda aleatoria:

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

# Definir el espacio de hiperparámetros con distribuciones
parametros_aleatorios = {
    'clasificador__C': uniform(0.1, 10),
    'clasificador__gamma': uniform(0.001, 1),
    'clasificador__kernel': ['rbf']
}

# Configurar RandomizedSearchCV
random_search = RandomizedSearchCV(pipeline, parametros_aleatorios, n_iter=10, cv=3, random_state=42)

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

# Mostrar los mejores parámetros encontrados
print("Mejores parámetros:", random_search.best_params_)
print("Mejor puntuación:", random_search.best_score_)

En este caso, RandomizedSearchCV explora una muestra aleatoria de combinaciones de hiperparámetros, lo que puede ser más práctico en problemas con espacios de búsqueda grandes. Al igual que con GridSearchCV, la integración con el Pipeline asegura que todas las etapas se consideren durante el proceso de optimización.

Además, es posible optimizar hiperparámetros de pasos intermedios del Pipeline. Por ejemplo, si queremos ajustar el número de características seleccionadas por un transformador:

from sklearn.feature_selection import SelectKBest, chi2

# Actualizar el Pipeline incluyendo SelectKBest
pipeline = Pipeline([
    ('escalador', StandardScaler()),
    ('seleccion', SelectKBest(score_func=chi2)),
    ('clasificador', SVC())
], memory='memory_cache')

# Definir el espacio de hiperparámetros incluyendo el transformador
parametros = {
    'seleccion__k': [50, 100, 200],
    'clasificador__C': [1, 10],
    'clasificador__gamma': [0.01, 0.001],
    'clasificador__kernel': ['rbf']
}

# Configurar GridSearchCV
grid_search = GridSearchCV(pipeline, parametros, cv=3)

# Ejecutar la búsqueda de hiperparámetros
grid_search.fit(X, y)

# Mostrar los mejores parámetros encontrados
print("Mejores parámetros:", grid_search.best_params_)
print("Mejor puntuación:", grid_search.best_score_)

Al incluir el hiperparámetro seleccion__k, GridSearchCV evalúa diferentes números de características seleccionadas por SelectKBest. Esta capacidad de ajustar múltiples etapas simultáneamente es una de las ventajas clave de usar Pipelines con herramientas de búsqueda de hiperparámetros.

También se pueden definir pasos personalizados e incluirlos en el Pipeline. Por ejemplo, si necesitamos un transformador específico:

from sklearn.base import BaseEstimator, TransformerMixin

class TransformadorPersonalizado(BaseEstimator, TransformerMixin):
    def fit(self, X, y=None):
        # Ajustar el transformador
        return self

    def transform(self, X):
        # Aplicar la transformación
        return X

# Actualizar el Pipeline con el transformador personalizado
pipeline = Pipeline([
    ('transformador', TransformadorPersonalizado()),
    ('clasificador', SVC())
], memory='memory_cache')

# Definir los hiperparámetros del transformador
parametros = {
    'clasificador__C': [1, 10],
    'clasificador__gamma': [0.01, 0.001],
    'clasificador__kernel': ['rbf']
}

# Configurar GridSearchCV
grid_search = GridSearchCV(pipeline, parametros, cv=3)

# Ejecutar la búsqueda de hiperparámetros
grid_search.fit(X, y)

# Mostrar los mejores parámetros encontrados
print("Mejores parámetros:", grid_search.best_params_)
print("Mejor puntuación:", grid_search.best_score_)

En este ejemplo, TransformadorPersonalizado es un transformador definido por el usuario que se integra en el Pipeline. Al incluirlo, podemos ajustar tanto los hiperparámetros del transformador como los del clasificador.

Es fundamental gestionar adecuadamente el parámetro memory en el Pipeline, especialmente cuando algunas etapas son costosas de computar. Al establecer memory='memory_cache', se habilita la memorización de las transformaciones, evitando cálculos redundantes y mejorando la eficiencia.

Por último, al trabajar con grandes conjuntos de datos, es recomendable utilizar validación cruzada más eficiente o limitar el número de combinaciones de hiperparámetros. Tanto GridSearchCV como RandomizedSearchCV permiten ajustar el parámetro cv y otros parámetros de control para optimizar el proceso de búsqueda de hiperparámetros.

Integrar GridSearchCV y RandomizedSearchCV con Pipelines en Scikit-Learn es una práctica esencial para construir modelos robustos y optimizados, aprovechando al máximo las capacidades de estas herramientas en un flujo de trabajo coherente y reproducible.

Evitando el sobreajuste y fugas de datos

El sobreajuste ocurre cuando un modelo de aprendizaje automático se ajusta demasiado a los datos de entrenamiento, capturando incluso el ruido y las fluctuaciones aleatorias. Esto resulta en un rendimiento pobre en datos nuevos. Una causa común de sobreajuste es la fuga de datos, que sucede cuando información del conjunto de prueba se filtra en el conjunto de entrenamiento, dando lugar a estimaciones demasiado optimistas.

Para evitar fugas de datos, es esencial asegurar que todas las etapas de preprocesamiento se ajusten únicamente con los datos de entrenamiento en cada partición de validación cruzada. Los Pipelines de Scikit-Learn proporcionan una estructura que garantiza este aislamiento, manteniendo el proceso de transformación y modelado encapsulado.

Por ejemplo, consideremos un escenario donde imputamos valores faltantes y luego aplicamos una clasificación:

import numpy as np
from sklearn.pipeline import Pipeline
from sklearn.impute import SimpleImputer
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import cross_val_score
from sklearn.datasets import load_breast_cancer

# Cargar los datos
data = load_breast_cancer()
X, y = data.data, data.target

# Introducir valores faltantes artificialmente
rng = np.random.default_rng(seed=42)  # Crear el generador con una semilla fija
X_missing = X.copy()
random_rows = rng.integers(0, X.shape[0], size=50)
random_cols = rng.integers(0, X.shape[1], size=50)
X_missing[random_rows, random_cols] = np.nan

# Crear el Pipeline con memoria
pipeline = Pipeline([
    ('imputacion', SimpleImputer(strategy='mean')),
    ('escalado', StandardScaler()),
    ('clasificacion', LogisticRegression())
], memory='cache_memory')

# Evaluar el modelo usando validación cruzada
puntuaciones = cross_val_score(pipeline, X_missing, y, cv=5)

print("Puntuaciones de validación cruzada:", puntuaciones)
print("Precisión media:", puntuaciones.mean())

En este ejemplo, se introducen valores faltantes en el conjunto de datos. Si realizáramos la imputación fuera del Pipeline, antes de la validación cruzada, podríamos introducir una fuga de datos, ya que la imputación estaría influenciada por todo el conjunto de datos, incluyendo información del conjunto de prueba. Al incluir la imputación dentro del Pipeline, garantizamos que en cada iteración de la validación cruzada, la estrategia de imputación se ajusta solo con los datos de entrenamiento, evitando fugas.

Otro aspecto crítico es evitar el sobreajuste al seleccionar características o ajustar hiperparámetros. Por ejemplo, si seleccionamos características utilizando todo el conjunto de datos antes de la validación cruzada, podemos introducir una fuga de datos. Lo correcto es incluir la selección de características dentro del Pipeline:

from sklearn.feature_selection import SelectKBest, f_classif

# Crear el Pipeline con selección de características
pipeline = Pipeline([
    ('imputacion', SimpleImputer(strategy='mean')),
    ('seleccion', SelectKBest(score_func=f_classif, k=10)),
    ('escalado', StandardScaler()),
    ('clasificacion', LogisticRegression())
], memory='cache_memory')

# Evaluar el modelo
puntuaciones = cross_val_score(pipeline, X_missing, y, cv=5)

print("Puntuaciones de validación cruzada:", puntuaciones)
print("Precisión media:", puntuaciones.mean())

Al incorporar SelectKBest dentro del Pipeline, aseguramos que la selección de características se realiza solo con los datos de entrenamiento en cada pliegue, evitando el sobreajuste y manteniendo la integridad del proceso.

Además, al ajustar hiperparámetros con GridSearchCV o RandomizedSearchCV, es importante que la validación cruzada interna se gestione adecuadamente. Podemos combinar Pipelines con búsqueda de hiperparámetros y cuidar de evitar fugas:

from sklearn.model_selection import GridSearchCV

# Definir el espacio de hiperparámetros
parametros = {
    'seleccion__k': [5, 10, 15],
    'clasificacion__C': [0.1, 1, 10]
}

# Configurar GridSearchCV
grid_search = GridSearchCV(pipeline, parametros, cv=5)

# Ejecutar la búsqueda
grid_search.fit(X_missing, y)

# Mostrar los mejores parámetros
print("Mejores parámetros:", grid_search.best_params_)
print("Mejor puntuación:", grid_search.best_score_)

Al utilizar GridSearchCV con el Pipeline, cada combinación de hiperparámetros se evalúa correctamente, evitando fugas de datos durante la selección de características y el entrenamiento del modelo.

Un error común es aplicar transformaciones que utilizan información futura. Por ejemplo, al escalar datos por características utilizando la media y desviación estándar del conjunto completo. Esto puede evitarse incluyendo el escalado dentro del Pipeline, garantizando que en cada pliegue, las estadísticas se calculen solo con los datos de entrenamiento.

Es fundamental tener en cuenta las etapas del Pipeline y cómo interactúan durante la validación cruzada. Mantener todas las transformaciones y ajustes dentro del Pipeline asegura que no haya interferencias entre el conjunto de entrenamiento y el de prueba, preservando la validez de las evaluaciones del modelo.

Otro ejemplo es al manejar variables categóricas. Si utilizamos OneHotEncoder fuera del Pipeline, podemos introducir nuevas categorías presentes en el conjunto de prueba que no estaban en el de entrenamiento. Al incluir el codificador dentro del Pipeline, evitamos este problema:

from sklearn.preprocessing import OneHotEncoder
from sklearn.compose import ColumnTransformer
import pandas as pd

# Crear un generador de números aleatorios moderno
rng = np.random.default_rng(seed=42)

# Supongamos que tenemos datos en un DataFrame
df = pd.DataFrame({
    'numerico': rng.standard_normal(100),  # Generar datos numéricos
    'categorico': rng.choice(['A', 'B', 'C'], size=100),  # Generar datos categóricos
    'objetivo': rng.choice([0, 1], size=100)  # Generar datos de objetivo
})

X = df[['numerico', 'categorico']]
y = df['objetivo']

# Definir el preprocesador
preprocesador = ColumnTransformer(transformers=[
    ('num', StandardScaler(), ['numerico']),
    ('cat', OneHotEncoder(handle_unknown='ignore'), ['categorico'])
])

# Crear el Pipeline completo
pipeline = Pipeline([
    ('preprocesado', preprocesador),
    ('clasificacion', LogisticRegression())
], memory='cache_memory')

# Evaluar el modelo
puntuaciones = cross_val_score(pipeline, X, y, cv=5)

print("Puntuaciones de validación cruzada:", puntuaciones)
print("Precisión media:", puntuaciones.mean())

Al usar handle_unknown='ignore' en OneHotEncoder y al incluirlo en el Pipeline, garantizamos que el modelo pueda manejar categorías desconocidas en el conjunto de prueba sin causar errores o fugas de datos.

En resumen, para evitar sobreajuste y fugas de datos, es crucial encapsular todas las etapas de preprocesamiento, selección de características y modelado dentro de un Pipeline. Esto asegura que en cada iteración de validación cruzada o durante el ajuste de hiperparámetros, no se filtrará información del conjunto de prueba al conjunto de entrenamiento, manteniendo la integridad y la generalización del modelo.

Validación cruzada anidada con Pipelines

La validación cruzada anidada es una técnica esencial para obtener estimaciones imparciales del rendimiento de un modelo cuando se realiza ajuste de hiperparámetros. Al combinar Pipelines con validación cruzada anidada en Scikit-Learn, se integran todas las etapas del preprocesamiento y modelado, garantizando una evaluación robusta y evitando el sobreajuste.

La necesidad de este enfoque surge porque al optimizar hiperparámetros utilizando validación cruzada, se corre el riesgo de obtener estimaciones optimistas del rendimiento. La validación cruzada anidada resuelve este problema introduciendo dos bucles: un bucle externo para evaluar el modelo y un bucle interno para seleccionar los hiperparámetros óptimos.

A continuación, se muestra un ejemplo práctico de cómo implementar la validación cruzada anidada con Pipelines en Scikit-Learn. Utilizaremos el conjunto de datos de dígitos escritos a mano y un clasificador SVM.

from sklearn.datasets import load_digits
from sklearn.model_selection import GridSearchCV, cross_val_score, KFold
from sklearn.svm import SVC
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
import numpy as np

# Cargar los datos
X, y = load_digits(return_X_y=True)

# Definir el Pipeline con memoria
pipeline = Pipeline([
    ('escalado', StandardScaler()),
    ('clasificador', SVC())
], memory='memoria_cache')

# Definir el espacio de hiperparámetros
parametros = {
    'clasificador__C': [0.1, 1, 10],
    'clasificador__gamma': [0.01, 0.001],
    'clasificador__kernel': ['rbf', 'linear']
}

# Configurar GridSearchCV para la validación interna
busqueda = GridSearchCV(pipeline, parametros, cv=5)

# Definir la validación cruzada externa
cv_externo = KFold(n_splits=5, shuffle=True, random_state=42)

# Realizar la validación cruzada anidada
puntuaciones = cross_val_score(busqueda, X, y, cv=cv_externo)

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

En este ejemplo, el Pipeline incluye un escalado de los datos con StandardScaler y un clasificador SVM. La búsqueda de los mejores hiperparámetros se realiza con GridSearchCV dentro del bucle interno de validación cruzada. El bucle externo, definido por KFold, se utiliza para evaluar el rendimiento del modelo con los hiperparámetros óptimos en datos no vistos.

La función cross_val_score ejecuta la validación cruzada anidada, asegurando que en cada partición externa, el modelo se entrene y valide utilizando exclusivamente los datos de entrenamiento, evitando cualquier fuga de datos. Esto proporciona una estimación más realista y generalizable del rendimiento del modelo.

Si el espacio de hiperparámetros es amplio y se desea reducir el tiempo de cómputo, es posible utilizar RandomizedSearchCV:

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

# Definir distribuciones de hiperparámetros
parametros_distribucion = {
    'clasificador__C': uniform(0.1, 10),
    'clasificador__gamma': uniform(0.001, 0.1),
    'clasificador__kernel': ['rbf']
}

# Configurar RandomizedSearchCV
busqueda_aleatoria = RandomizedSearchCV(pipeline, parametros_distribucion, n_iter=10, cv=5, random_state=42)

# Realizar la validación cruzada anidada
puntuaciones = cross_val_score(busqueda_aleatoria, X, y, cv=cv_externo)

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

Con RandomizedSearchCV, se exploran aleatoriamente combinaciones de hiperparámetros, lo que puede ser más eficiente computacionalmente mientras se mantiene la efectividad en la búsqueda de parámetros óptimos.

También es posible incluir etapas adicionales en el Pipeline, como la selección de características, y ajustar sus hiperparámetros dentro de la validación cruzada anidada:

from sklearn.feature_selection import SelectKBest, chi2
from sklearn.preprocessing import MinMaxScaler

# Actualizar el Pipeline con selección de características
pipeline = Pipeline([
    ('escalado', MinMaxScaler()),
    ('seleccion', SelectKBest(score_func=chi2)),
    ('clasificador', SVC())
], memory='memoria_cache')

# Definir el espacio de hiperparámetros incluyendo 'k'
parametros = {
    'seleccion__k': [20, 30, 40],
    'clasificador__C': [0.1, 1, 10],
    'clasificador__gamma': [0.01, 0.001],
    'clasificador__kernel': ['rbf']
}

# Configurar GridSearchCV
busqueda = GridSearchCV(pipeline, parametros, cv=5)

# Realizar la validación cruzada anidada
puntuaciones = cross_val_score(busqueda, X, y, cv=cv_externo)

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

En este caso, SelectKBest se utiliza para seleccionar las mejores características basadas en la prueba chi-cuadrado, y el valor de k se optimiza durante el ajuste de hiperparámetros. La validación cruzada anidada garantiza que tanto la selección de características como el ajuste del modelo se realicen de manera imparcial, utilizando únicamente los datos de entrenamiento en cada pliegue externo.

La combinación de Pipelines y validación cruzada anidada es especialmente útil para prevenir el sobreajuste y obtener estimaciones fiables del rendimiento del modelo. Al encapsular todas las etapas del preprocesamiento y modelado dentro del Pipeline, se asegura una separación estricta entre los datos de entrenamiento y prueba, evitando fugas de datos y mejorando la generalización del modelo.

Es importante tener en cuenta que la validación cruzada anidada puede ser computacionalmente costosa debido a la naturaleza doblemente iterativa del proceso. Sin embargo, las estimaciones de rendimiento obtenidas son más realistas y ayudan a seleccionar modelos que realmente funcionarán bien en datos nuevos.

Al aplicar estas técnicas con Scikit-Learn en Python, aprovechamos las funcionalidades más recientes y eficientes, garantizando que nuestro flujo de trabajo esté actualizado y sea robusto.

Ejemplo práctico de ajuste de hiperparámetros

En este ejemplo práctico, se demostrará el proceso de ajuste de hiperparámetros utilizando Pipelines y GridSearchCV en Scikit-Learn para construir un modelo de clasificación. El objetivo es predecir la presencia de cáncer de mama utilizando el conjunto de datos Breast Cancer Wisconsin.

Primero, se importan las librerías necesarias y se carga el conjunto de datos:

from sklearn.datasets import load_breast_cancer
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import PCA
from sklearn.svm import SVC
from sklearn.model_selection import GridSearchCV, StratifiedKFold, train_test_split
from sklearn.metrics import classification_report

# Cargar los datos
data = load_breast_cancer()
X, y = data.data, data.target

A continuación, se crea un Pipeline que incluye el escalado de características, reducción de dimensionalidad con PCA y un clasificador SVM:

# Crear el Pipeline con memoria
pipeline = Pipeline([
    ('escalado', StandardScaler()),
    ('pca', PCA()),
    ('clasificador', SVC())
], memory='cache_dir')

El parámetro memory='cache_dir' permite almacenar en caché los transformadores para mejorar la eficiencia en cálculos repetitivos.

Se define el espacio de hiperparámetros para realizar la búsqueda:

# Definir el espacio de hiperparámetros
parametros = {
    'pca__n_components': [5, 10, 15],
    'clasificador__kernel': ['rbf', 'linear'],
    'clasificador__C': [0.1, 1, 10],
    'clasificador__gamma': [0.001, 0.01, 0.1]
}

Este espacio incluye diferentes números de componentes principales para el PCA y varios valores para los parámetros kernel, C y gamma del SVM.

Se configura la validación cruzada y se crea GridSearchCV:

# Definir la estrategia de validación cruzada
cv = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)

# Configurar GridSearchCV
grid_search = GridSearchCV(pipeline, parametros, cv=cv, scoring='accuracy', n_jobs=-1)

El uso de StratifiedKFold garantiza que la proporción de clases se mantenga en cada partición, lo cual es crucial para problemas de clasificación.

Se ejecuta la búsqueda de hiperparámetros:

# Ejecutar la búsqueda de hiperparámetros
grid_search.fit(X, y)

# Mostrar los mejores parámetros y precisión obtenida
print("Mejores parámetros:", grid_search.best_params_)
print("Mejor precisión en validación cruzada:", grid_search.best_score_)

Después de encontrar los mejores parámetros, se evalúa el rendimiento del modelo en un conjunto de prueba independiente:

# Dividir los datos en entrenamiento y prueba
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, stratify=y, random_state=42)

# Entrenar el mejor modelo con los datos de entrenamiento
mejor_modelo = grid_search.best_estimator_
mejor_modelo.fit(X_train, y_train)

# Predecir en el conjunto de prueba
y_pred = mejor_modelo.predict(X_test)

# Generar el informe de clasificación
print(classification_report(y_test, y_pred))

El informe de clasificación proporciona métricas detalladas como precisión, exhaustividad y puntaje F1 para cada clase, permitiendo una comprensión profunda del rendimiento del modelo.

Si se desea reducir el tiempo de cómputo explorando aleatoriamente el espacio de hiperparámetros, se puede utilizar RandomizedSearchCV:

from sklearn.model_selection import RandomizedSearchCV
from scipy.stats import randint, uniform

# Definir distribuciones de hiperparámetros
param_dist = {
    'pca__n_components': randint(5, 15),
    'clasificador__kernel': ['rbf', 'linear'],
    'clasificador__C': uniform(0.1, 10),
    'clasificador__gamma': uniform(0.001, 0.1)
}

# Configurar RandomizedSearchCV
random_search = RandomizedSearchCV(pipeline, param_distributions=param_dist, n_iter=20, cv=cv, scoring='accuracy', n_jobs=-1, random_state=42)

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

# Mostrar los mejores parámetros y precisión obtenida
print("Mejores parámetros (RandomizedSearchCV):", random_search.best_params_)
print("Mejor precisión en validación cruzada:", random_search.best_score_)

Esta técnica permite una exploración más amplia del espacio de hiperparámetros con menos iteraciones, siendo más eficiente en términos computacionales.

Para visualizar el impacto de los hiperparámetros en el rendimiento, se pueden extraer y analizar los resultados de la búsqueda:

import pandas as pd
import matplotlib.pyplot as plt

# Convertir los resultados en un DataFrame
resultados = pd.DataFrame(grid_search.cv_results_)

# Mostrar los 5 mejores resultados
print(resultados.nlargest(5, 'mean_test_score'))

Este análisis ayuda a comprender cómo afectan los diferentes hiperparámetros al modelo y a tomar decisiones informadas sobre su ajuste.

Finalmente, se puede guardar el modelo entrenado para uso futuro:

import joblib

# Guardar el mejor modelo
joblib.dump(mejor_modelo, 'mejor_modelo.pkl')

# Cargar el modelo guardado
modelo_cargado = joblib.load('mejor_modelo.pkl')

El uso de joblib permite la persistencia del Pipeline completo, incluyendo todos los pasos de preprocesamiento y el clasificador optimizado.

Este ejemplo práctico demuestra cómo integrar todas las etapas del preprocesamiento, búsqueda de hiperparámetros y evaluación en un Pipeline, promoviendo buenas prácticas y garantizando la reproducibilidad del modelo en proyectos de aprendizaje automático.

Aprende ScikitLearn GRATIS online

Ejercicios de esta lección Pipelines y Validación Cruzada

Evalúa tus conocimientos de esta lección Pipelines y Validación Cruzada 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

  • Aprender a integrar Pipelines con cross_val_score.
  • Validar modelos sin fugas de datos.
  • Dominar la configuración de StratifiedKFold.
  • Automatizar el escalado y procesamiento de características.
  • Aplicar técnicas de selección de características en Pipelines.