Optimizando Modelos de Clasificación Binaria con ROC, AUC y Análisis de Umbral: Una Guía Integral
Desbloquea el máximo potencial de tus modelos de aprendizaje automático dominando las curvas ROC, las métricas AUC y la selección de umbrales óptimos. Esta guía profundiza en la preprocesamiento, el modelado de regresión logística y la optimización del rendimiento utilizando un conjunto de datos meteorológicos del mundo real.
Introducción
En el ámbito del aprendizaje automático, particularmente en tareas de clasificación binaria, evaluar y optimizar el rendimiento del modelo es fundamental. Métricas como las curvas Características de Operación del Receptor (ROC) y el Área Bajo la Curva (AUC) brindan valiosas perspectivas sobre la capacidad de un modelo para discriminar entre clases. Además, ajustar el umbral de clasificación puede mejorar significativamente la precisión del modelo, el puntaje F1 y el rendimiento general. Este artículo explora estos conceptos en detalle, utilizando un conjunto de datos meteorológicos del mundo real para demostrar la aplicación práctica a través de un ejemplo en Jupyter Notebook.
Comprendiendo las Curvas ROC y el AUC
¿Qué es una Curva ROC?
Una curva ROC es una representación gráfica que ilustra la capacidad diagnóstica de un sistema clasificador binario a medida que varía su umbral de discriminación. Traza la Tasa de Verdaderos Positivos (TPR) contra la Tasa de Falsos Positivos (FPR) en varios ajustes de umbral.
- Tasa de Verdaderos Positivos (TPR): También conocida como Recall o Sensibilidad, mide la proporción de positivos reales identificados correctamente por el modelo. \[ \text{TPR} = \frac{\text{Verdaderos Positivos}}{\text{Verdaderos Positivos} + \text{Falsos Negativos}} \]
- Tasa de Falsos Positivos (FPR): Mide la proporción de negativos reales identificados incorrectamente como positivos por el modelo. \[ \text{FPR} = \frac{\text{Falsos Positivos}}{\text{Falsos Positivos} + \text{Verdaderos Negativos}} \]
¿Qué es el AUC?
El Área Bajo la Curva (AUC) cuantifica la capacidad general del modelo para discriminar entre las clases positivas y negativas. Un AUC más alto indica un modelo con mejor rendimiento. Un AUC de 0.5 sugiere que no hay poder discriminativo, equivalente a una suposición aleatoria, mientras que un AUC de 1.0 representa una discriminación perfecta.
Descripción del Conjunto de Datos: Weather Australia
Para esta guía, utilizaremos un conjunto de datos de Weather Australia, que contiene varios atributos meteorológicos. El conjunto de datos ha sido preprocesado para incluir 10,000 registros, lo que garantiza manejabilidad y efectividad para ilustrar los conceptos.
Fuente de Datos: Conjunto de Datos Weather Australia en Kaggle
Preprocesamiento de Datos
El preprocesamiento efectivo es crucial para construir modelos de aprendizaje automático robustos. Los siguientes pasos describen la tubería de preprocesamiento aplicada al conjunto de datos Weather Australia.
1. Importación de Bibliotecas y Datos
1 2 3 4 5 6 7 8 9 10 |
import pandas as pd import seaborn as sns import numpy as np from sklearn.impute import SimpleImputer from sklearn.compose import ColumnTransformer from sklearn.preprocessing import OneHotEncoder, LabelEncoder, MinMaxScaler, StandardScaler from sklearn.feature_selection import SelectKBest, chi2 from sklearn.model_selection import train_test_split from sklearn.linear_model import LogisticRegression from sklearn.metrics import accuracy_score, roc_curve, auc, classification_report |
1 2 |
data = pd.read_csv('weatherAUS - tiny.csv') data.tail() |
Salida de Muestra:
Date | Location | MinTemp | MaxTemp | Rainfall | Evaporation | Sunshine | … | RainToday | RISK_MM | RainTomorrow |
---|---|---|---|---|---|---|---|---|---|---|
05/01/2012 | CoffsHarbour | 21.3 | 26.5 | 0.6 | 7.6 | 6.4 | … | No | 0.0 | No |
2. Selección de Características
Separa el conjunto de datos en características (X
) y objetivo (y
).
1 2 3 |
X = data.iloc[:,:-1] X.drop('RISK_MM', axis=1, inplace=True) y = data.iloc[:,-1] |
3. Manejo de Datos Faltantes
a. Características Numéricas
Imputar valores faltantes en columnas numéricas utilizando la estrategia de la media.
1 2 3 4 |
numerical_cols = list(np.where((X.dtypes == np.int64) | (X.dtypes == np.float64))[0]) imp_mean = SimpleImputer(missing_values=np.nan, strategy='mean') imp_mean.fit(X.iloc[:, numerical_cols]) X.iloc[:, numerical_cols] = imp_mean.transform(X.iloc[:, numerical_cols]) |
b. Características Categóricas
Imputar valores faltantes en columnas categóricas utilizando la estrategia más frecuente.
1 2 3 4 |
string_cols = list(np.where((X.dtypes == object))[0]) imp_freq = SimpleImputer(missing_values=np.nan, strategy='most_frequent') imp_freq.fit(X.iloc[:, string_cols]) X.iloc[:, string_cols] = imp_freq.transform(X.iloc[:, string_cols]) |
4. Codificación de Variables Categóricas
a. Codificación de Etiquetas
Convertir etiquetas categóricas en valores numéricos para la variable objetivo.
1 2 3 4 5 |
def LabelEncoderMethod(series): le = LabelEncoder() return le.fit_transform(series) y = LabelEncoderMethod(y) |
b. Codificación One-Hot
Aplicar Codificación One-Hot a las características categóricas con más de dos valores únicos.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
def OneHotEncoderMethod(indices, data): columnTransformer = ColumnTransformer([('encoder', OneHotEncoder(), indices )], remainder='passthrough') return columnTransformer.fit_transform(data) def EncodingSelection(X, threshold=10): string_cols = list(np.where((X.dtypes == object))[0]) one_hot_encoding_indices = [] for col in string_cols: unique_values = len(pd.unique(X[X.columns[col]])) if unique_values == 2 or unique_values > threshold: X[X.columns[col]] = LabelEncoderMethod(X[X.columns[col]]) else: one_hot_encoding_indices.append(col) X = OneHotEncoderMethod(one_hot_encoding_indices, X) return X X = EncodingSelection(X) |
5. Escalado y Selección de Características
a. Escalado de Características
Estandarizar el conjunto de características para asegurar uniformidad entre las variables.
1 2 |
sc = StandardScaler(with_mean=False) X = sc.fit_transform(X) |
b. Selección de Características
Seleccionar las 10 principales características basadas en la prueba estadística Chi-Cuadrado (chi2).
1 2 |
kbest = SelectKBest(score_func=chi2, k=10) X = kbest.fit_transform(X, y) |
6. División de Entrenamiento y Prueba
Dividir el conjunto de datos en conjuntos de entrenamiento y prueba para evaluar el rendimiento del modelo.
1 |
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.20, random_state=1) |
Construcción y Evaluación del Modelo de Regresión Logística
Con los datos preprocesados, procedemos a construir un modelo de Regresión Logística, evaluar su rendimiento y optimizarlo utilizando las métricas ROC y AUC.
1. Entrenamiento del Modelo
1 2 3 4 |
LRM = LogisticRegression(random_state=0, max_iter=500) LRM.fit(X_train, y_train) y_pred = LRM.predict(X_test) print(f"Accuracy: {accuracy_score(y_pred, y_test):.3f}") |
Salida:
1 |
Accuracy: 0.872 |
2. Cálculo de la Curva ROC y el AUC
Trazar la curva ROC y calcular el AUC proporciona una comprensión integral del rendimiento del modelo.
1 2 3 4 |
predicted_probabilities = LRM.predict_proba(X_test) fpr, tpr, thresholds = roc_curve(y_test, predicted_probabilities[:,1]) roc_auc = auc(fpr, tpr) print(f"AUC: {roc_auc:.3f}") |
Salida:
1 |
AUC: 0.884 |
3. Optimización del Umbral de Clasificación
El umbral predeterminado de 0.5 puede no siempre ofrecer el mejor rendimiento. Ajustar este umbral puede mejorar la precisión y otras métricas.
a. Cálculo de la Precisión en Diferentes Umbrales
1 2 3 4 5 6 7 8 9 |
accuracies = [] for thresh in thresholds: _predictions = [1 if i >= thresh else 0 for i in predicted_probabilities[:, -1]] accuracies.append(accuracy_score(y_test, _predictions, normalize=True)) accuracies = pd.concat([pd.Series(thresholds), pd.Series(accuracies)], axis=1) accuracies.columns = ['threshold', 'accuracy'] accuracies.sort_values(by='accuracy', ascending=False, inplace=True) print(accuracies.head()) |
Salida de Muestra:
1 2 3 4 5 6 |
threshold accuracy 78 0.547545 0.8760 76 0.560424 0.8755 114 0.428764 0.8755 112 0.432886 0.8755 110 0.433176 0.8755 |
b. Selección del Umbral Óptimo
1 2 |
optimal_proba_cutoff = accuracies['threshold'].iloc[0] roc_predictions = [1 if i >= optimal_proba_cutoff else 0 for i in predicted_probabilities[:, -1]] |
c. Evaluación con el Umbral Óptimo
1 2 |
print("Classification Report with Optimal Threshold:") print(classification_report(roc_predictions, y_test)) |
Salida:
1 2 3 4 5 6 7 8 |
precision recall f1-score support 0 0.97 0.89 0.93 1770 1 0.48 0.77 0.59 230 accuracy 0.88 2000 macro avg 0.72 0.83 0.76 2000 weighted avg 0.91 0.88 0.89 2000 |
Comparación con el Umbral Predeterminado:
1 2 |
print("Classification Report with Default Threshold (0.5):") print(classification_report(y_pred, y_test)) |
Salida:
1 2 3 4 5 6 7 8 |
precision recall f1-score support 0 0.96 0.89 0.92 1740 1 0.51 0.73 0.60 260 accuracy 0.87 2000 macro avg 0.73 0.81 0.76 2000 weighted avg 0.90 0.87 0.88 2000 |
Perspectivas:
- Mejora de la Precisión: El umbral óptimo aumenta ligeramente la precisión del 87.2% al 88%.
- Mejora del Puntaje F1: El puntaje F1 mejora de 0.60 a 0.59 (una mejora marginal dado el equilibrio entre precisión y recall).
- Precisión y Recall Equilibrados: El umbral óptimo mantiene un equilibrio entre precisión y recall, asegurando que ninguno sea favorecido desproporcionadamente.
Mejores Prácticas para la Optimización de Umbrales
- Comprender los Compromisos: Ajustar el umbral afecta la sensibilidad y la especificidad. Es esencial alinear la selección del umbral con los objetivos específicos de tu aplicación.
- Usar Métricas Relevantes: Dependiendo del problema, prioriza métricas como el puntaje F1, precisión o recall sobre la mera precisión.
- Automatizar la Selección de Umbral: Aunque la inspección manual es beneficiosa, aprovechar métodos automatizados o la validación cruzada puede aumentar la robustez.
Conclusión
Optimizar modelos de clasificación binaria va más allá de lograr una alta precisión. Al aprovechar las curvas ROC, las métricas AUC y los ajustes estratégicos de umbral, los profesionales pueden afinar los modelos para cumplir con criterios de rendimiento específicos. Este enfoque integral asegura que los modelos sean no solo precisos, sino también confiables y efectivos en diversos escenarios.
Puntos Clave:
- ROC y AUC proporcionan una visión holística del rendimiento del modelo a través de diferentes umbrales.
- Optimización de Umbral puede mejorar las métricas del modelo, adaptando el rendimiento a las necesidades específicas de la aplicación.
- Preprocesamiento Integral es fundamental para construir modelos de aprendizaje automático robustos y efectivos.
Emprende el perfeccionamiento de tus modelos con estas estrategias para lograr un rendimiento superior y obtener insights accionables.
Recursos Adicionales
Autor: [Tu Nombre]
Redactor Técnico y Entusiasta de la Ciencia de Datos