ScikitLearn
Tutorial ScikitLearn: Preprocesamiento de datos desbalanceados
Scikit-Learn: Preprocesamiento de datos desbalanceados. Aprende a manejar datos desequilibrados en aprendizaje automático utilizando técnicas como SMOTE, ensamblados y evaluaciones especializadas.
Aprende ScikitLearn GRATIS y certifícateProblemas causados por datos desbalanceados
En el aprendizaje automático, los datos desbalanceados son un desafío significativo que puede afectar negativamente el rendimiento de los modelos de clasificación. Un conjunto de datos está desbalanceado cuando las clases no se distribuyen de manera equitativa; es decir, una o varias clases tienen muchas más muestras que otras. Este desequilibrio puede conducir a modelos que están sesgados hacia las clases mayoritarias, ignorando las minoritarias.
Por ejemplo, en un problema de detección de fraude, las transacciones fraudulentas representan una fracción mínima del total. Si entrenamos un modelo sin abordar el desbalanceo, es probable que este prediga siempre la clase mayoritaria (no fraude), obteniendo aparentemente una alta precisión, pero fallando en identificar correctamente los casos de fraude.
Las consecuencias principales de trabajar con datos desbalanceados son:
- Sesgo del modelo: El modelo aprende principalmente de la clase mayoritaria, lo que reduce su capacidad para generalizar y detectar correctamente las clases minoritarias.
- Métricas de evaluación engañosas: Medidas como la precisión global pueden ser poco informativas. Es fundamental utilizar métricas como la matriz de confusión, recall, precision o F1-score que proporcionen una visión más detallada del rendimiento por clase.
- Problemas en el criterio de parada: Algunos algoritmos pueden considerar que han convergido antes de tiempo si no se ajustan adecuadamente a la clase minoritaria.
En Scikit-Learn, si se utilizan modelos sin ajustar los parámetros correspondientes, estos pueden ser afectados por los datos desbalanceados. Algunos algoritmos ofrecen parámetros para manejar este problema. Por ejemplo:
- En árboles de decisión y bosques aleatorios, podemos ajustar el parámetro
class_weight='balanced'
para penalizar las clases en función de su frecuencia. - Para máquinas de vectores de soporte (SVM), el parámetro
class_weight
también puede ser utilizado para equilibrar el impacto de las clases.
from sklearn.ensemble import RandomForestClassifier
# Crear un modelo con ajuste de pesos para clases desbalanceadas
modelo = RandomForestClassifier(class_weight='balanced')
Además, es importante analizar la distribución de clases antes de entrenar el modelo. Podemos utilizar la función value_counts()
de Pandas para visualizar el desbalanceo:
import pandas as pd
# Supongamos que 'y' es nuestra variable objetivo
conteo_clases = y.value_counts()
print(conteo_clases)
Este análisis preliminar nos permite tomar decisiones informadas sobre cómo abordar el desbalanceo, ya sea mediante técnicas de sobremuestreo, submuestreo o ajustando los parámetros del modelo.
Otro problema derivado es la sobreajuste en la clase minoritaria si se utiliza sobremuestreo sin precaución. Al replicar excesivamente las muestras minoritarias, el modelo puede aprender detalles específicos del conjunto de entrenamiento que no generalizan bien a datos nuevos.
Es crucial también considerar la estratificación al dividir los datos en conjuntos de entrenamiento y prueba. Al utilizar train_test_split
de Scikit-Learn, podemos asegurarnos de que la proporción de clases se mantiene en ambos conjuntos:
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, stratify=y, random_state=42)
La estratificación garantiza que ambas particiones representen adecuadamente la distribución original de las clases, lo cual es esencial para una evaluación justa del modelo.
En resumen, ignorar el desbalanceo de clases puede llevar a modelos ineficaces y conclusiones erróneas. Es fundamental reconocer estos problemas y aplicar técnicas adecuadas para mitigarlos, garantizando así un aprendizaje más robusto y equitativo.
Técnicas de sobremuestreo y submuestreo
En el preprocesamiento de datos desbalanceados, las técnicas de sobremuestreo y submuestreo son fundamentales para equilibrar la distribución de clases y mejorar el rendimiento de los modelos de aprendizaje automático. Estas técnicas ajustan el conjunto de datos, ya sea aumentando las muestras de la clase minoritaria o reduciendo las de la clase mayoritaria.
El sobremuestreo consiste en incrementar el número de muestras de la clase minoritaria. Una forma sencilla de hacerlo es mediante el sobremuestreo aleatorio, donde se duplican aleatoriamente las muestras existentes de la clase minoritaria hasta equilibrar las clases. Esto puede realizarse utilizando funciones básicas de Python o herramientas de Scikit-Learn.
Por otro lado, el submuestreo implica reducir el número de muestras de la clase mayoritaria. El submuestreo aleatorio elimina aleatoriamente muestras de la clase mayoritaria hasta alcanzar un equilibrio con la clase minoritaria. Aunque este método puede ser efectivo, existe el riesgo de perder información valiosa al descartar datos.
A continuación, se muestra cómo implementar el sobremuestreo aleatorio utilizando Scikit-Learn y NumPy:
import numpy as np
from sklearn.datasets import make_classification
# Crear un conjunto de datos desbalanceado
X, y = make_classification(n_samples=1000, n_features=20,
n_classes=2, weights=[0.9, 0.1],
random_state=42)
# Separar las clases mayoritaria y minoritaria
X_mayoritaria = X[y == 0]
X_minoritaria = X[y == 1]
# Número de muestras que necesitamos agregar a la clase minoritaria
n_muestras_a_agregar = len(X_mayoritaria) - len(X_minoritaria)
# Crear un generador aleatorio moderno con semilla
rng = np.random.default_rng(seed=42)
# Realizar sobremuestreo aleatorio
indices_aleatorios = rng.integers(0, len(X_minoritaria), size=n_muestras_a_agregar)
X_minoritaria_sobremuestreada = X_minoritaria[indices_aleatorios]
y_minoritaria_sobremuestreada = np.ones(n_muestras_a_agregar)
# Concatenar las muestras originales y sobremuestreadas
X_sobremuestreado = np.vstack((X, X_minoritaria_sobremuestreada))
y_sobremuestreado = np.hstack((y, y_minoritaria_sobremuestreada))
# Verificar las proporciones después del sobremuestreo
from collections import Counter
print("Distribución de clases después del sobremuestreo:", Counter(y_sobremuestreado))
En este ejemplo, hemos utilizado NumPy para duplicar aleatoriamente muestras de la clase minoritaria. El resultado es un conjunto de datos equilibrado que puede mejorar la capacidad del modelo para aprender las características de ambas clases.
El submuestreo aleatorio puede implementarse de manera similar, eliminando muestras de la clase mayoritaria:
from sklearn.utils import resample
# Separar las muestras de cada clase
X_mayoritaria = X[y == 0]
y_mayoritaria = y[y == 0]
X_minoritaria = X[y == 1]
y_minoritaria = y[y == 1]
# Submuestrear la clase mayoritaria
X_mayoritaria_submuestreada, y_mayoritaria_submuestreada = resample(
X_mayoritaria, y_mayoritaria,
replace=False,
n_samples=len(X_minoritaria),
random_state=42
)
# Combinar las clases submuestreadas
X_submuestreado = np.vstack((X_mayoritaria_submuestreada, X_minoritaria))
y_submuestreado = np.hstack((y_mayoritaria_submuestreada, y_minoritaria))
Aquí, hemos utilizado la función resample
de Scikit-Learn para seleccionar aleatoriamente una muestra de la clase mayoritaria sin reemplazo. Esto crea un conjunto equilibrado pero reduce la cantidad total de datos disponibles para el entrenamiento.
Es importante considerar las implicaciones de cada técnica. El sobremuestreo aumenta el tamaño del conjunto de datos y puede llevar a sobreajuste si se duplican muchas muestras. El submuestreo reduce el tamaño del conjunto y puede provocar pérdida de información relevante de la clase mayoritaria.
Para abordar estas limitaciones, se pueden utilizar métodos más avanzados como el sobremuestreo sintético, que genera muestras artificiales de la clase minoritaria. Técnicas como SMOTE (Synthetic Minority Over-sampling Technique) crean nuevas muestras sintetizando características existentes. Aunque SMOTE no está incluido directamente en Scikit-Learn, es posible implementarlo o utilizar bibliotecas complementarias especializadas.
Además, es posible combinar ambas técnicas en métodos híbridos que aplican sobremuestreo a la clase minoritaria y submuestreo a la clase mayoritaria. Esto busca equilibrar el conjunto de datos sin los inconvenientes de cada técnica por separado.
Al integrar estas técnicas en el proceso de modelado, es esencial utilizar validación cruzada para evaluar adecuadamente el rendimiento y evitar sesgos. También es recomendable aplicar el sobremuestreo o submuestreo únicamente al conjunto de entrenamiento para no alterar la distribución real de los datos de prueba.
Por último, es crucial adaptar la técnica elegida al contexto específico del problema y al tipo de datos. No existe una solución universal, y la efectividad de cada método puede variar según el conjunto de datos y el modelo utilizado.
Algoritmos de sobremuestreo avanzados como SMOTE y variantes
En el contexto del aprendizaje automático, manejar datos desbalanceados es esencial para construir modelos eficaces. Los algoritmos de sobremuestreo avanzados como SMOTE (Synthetic Minority Over-sampling Technique) y sus variantes ofrecen soluciones sofisticadas para equilibrar las clases en datasets donde la clase minoritaria es significativamente menor que la mayoritaria.
SMOTE es una técnica que genera nuevas muestras sintéticas de la clase minoritaria en lugar de simplemente replicar ejemplos existentes. Esto se logra interpolando entre muestras cercanas en el espacio de características, lo que ayuda a que el modelo generalice mejor y no se sobreajuste a datos repetidos. En Scikit-Learn, SMOTE está integrado, facilitando su implementación en proyectos de aprendizaje supervisado.
Para utilizar SMOTE en Scikit-Learn, es necesario importar el módulo correspondiente y aplicarlo al conjunto de datos de entrenamiento:
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from imblearn.over_sampling import SMOTE
from sklearn.linear_model import LogisticRegression
# Generar un conjunto de datos desbalanceado
X, y = make_classification(n_samples=1000, n_features=20, n_classes=2,
weights=[0.9, 0.1], random_state=42)
# Dividir en conjuntos de entrenamiento y prueba con estratificación
X_train, X_test, y_train, y_test = train_test_split(X, y, stratify=y,
random_state=42)
# Aplicar escalado a los datos
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)
# Aplicar SMOTE al conjunto de entrenamiento
smote = SMOTE(random_state=42)
X_train_smote, y_train_smote = smote.fit_resample(X_train, y_train)
# Entrenar un modelo de regresión logística
modelo = LogisticRegression()
modelo.fit(X_train_smote, y_train_smote)
En este ejemplo, se ha utilizado SMOTE para generar muestras sintéticas de la clase minoritaria antes de entrenar el modelo. Es importante destacar que el sobremuestreo debe aplicarse únicamente al conjunto de entrenamiento para evitar introducir sesgos en la evaluación del modelo.
Además de SMOTE, existen variantes que combinan técnicas de sobremuestreo y submuestreo, mejorando aún más el equilibrio de las clases y la calidad del modelo:
- SMOTE Tomek Links: Combina SMOTE con la eliminación de Tomek Links, que son pares de muestras de clases opuestas muy cercanas entre sí. Esto ayuda a limpiar el ruido y definir mejor los límites entre clases.
- SMOTE ENN (Edited Nearest Neighbours): Combina SMOTE con la eliminación de muestras mal clasificadas por sus vecinos más cercanos, refinando el espacio de características y eliminando posibles outliers.
Para implementar SMOTE Tomek Links en Scikit-Learn:
from imblearn.combine import SMOTETomek
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import classification_report
from collections import Counter
# Generar un conjunto de datos desbalanceado
X, y = make_classification(n_samples=1000, n_features=20, n_classes=2,
weights=[0.9, 0.1], random_state=42)
# Dividir en conjuntos de entrenamiento y prueba
X_train, X_test, y_train, y_test = train_test_split(X, y, stratify=y, random_state=42)
# Aplicar SMOTE Tomek Links
smote_tomek = SMOTETomek(random_state=42)
X_train_st, y_train_st = smote_tomek.fit_resample(X_train, y_train)
# Verificar la nueva distribución de clases
print("Distribución de clases después de SMOTE Tomek Links:", Counter(y_train_st))
# Entrenar el modelo
modelo = LogisticRegression(random_state=42)
modelo.fit(X_train_st, y_train_st)
# Evaluar el modelo
y_pred = modelo.predict(X_test)
print(classification_report(y_test, y_pred))
La utilización de SMOTE ENN es similar:
from imblearn.combine import SMOTEENN
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import classification_report
# Aplicar SMOTE ENN
smote_enn = SMOTEENN(random_state=42)
X_train_se, y_train_se = smote_enn.fit_resample(X_train, y_train)
# Verificar la nueva distribución de clases
print("Distribución de clases después de SMOTE ENN:", Counter(y_train_se))
# Entrenar el modelo
modelo = LogisticRegression(random_state=42)
modelo.fit(X_train_se, y_train_se)
# Evaluar el modelo
y_pred = modelo.predict(X_test)
print(classification_report(y_test, y_pred))
Al seleccionar entre SMOTE y sus variantes, es crucial considerar las características específicas del conjunto de datos y el comportamiento del modelo. Las variantes que combinan sobremuestreo y submuestreo pueden ser más efectivas en situaciones donde existen outliers o ruido en las clases.
Una palabra clave en este contexto es la interpolación, que es el proceso mediante el cual SMOTE genera nuevas muestras sintéticas. La interpolación lineal entre un punto de la clase minoritaria y sus vecinos crea ejemplos realistas que enriquecen el modelo sin duplicar datos existentes.
Es relevante también mencionar que, al utilizar estas técnicas avanzadas, las métricas de evaluación del modelo pueden mostrar mejoras significativas en la detección de la clase minoritaria. Sin embargo, es fundamental realizar una validación cruzada adecuada y utilizar métricas como la curva ROC, el AUC o el F1-score, que reflejan mejor el rendimiento en contextos desbalanceados.
Otro aspecto a considerar es el ajuste de los parámetros de SMOTE y sus variantes. Por ejemplo, el parámetro k_neighbors
controla el número de vecinos utilizados para la interpolación:
smote = SMOTE(k_neighbors=5, random_state=42)
Ajustar este parámetro puede influir en la diversidad y representatividad de las muestras sintéticas generadas. Un valor adecuado de k_neighbors
depende de la densidad de la clase minoritaria y debe ser seleccionado cuidadosamente.
En el caso de SMOTE Tomek Links y SMOTE ENN, los parámetros adicionales permiten controlar la estrategia de eliminación de muestras:
smote_tomek = SMOTETomek(tomek=TomekLinks(sampling_strategy='all'),
random_state=42)
La configuración de estos parámetros debe basarse en un análisis detallado de los datos y pruebas experimentales para encontrar la combinación óptima que mejore el rendimiento del modelo sin introducir sobreajuste.
Es importante tener en cuenta que, aunque SMOTE y sus variantes son herramientas poderosas, no sustituyen un buen entendimiento de los datos y una correcta ingeniería de características. La calidad de los datos sigue siendo un factor determinante en el éxito de cualquier modelo de aprendizaje automático.
Finalmente, la integración de estos algoritmos en pipelines de Scikit-Learn permite automatizar el proceso y garantizar que las transformaciones se apliquen de manera consistente:
from sklearn.pipeline import Pipeline
pipeline = Pipeline([
('scaler', StandardScaler()),
('smote', SMOTE(random_state=42)),
('modelo', LogisticRegression())
], memory = None)
pipeline.fit(X_train, y_train)
Este enfoque asegura que el preprocesamiento, el sobremuestreo y el entrenamiento del modelo se realicen en secuencia, facilitando la reproducibilidad y mantenimiento del código.
En resumen, los algoritmos de sobremuestreo avanzados como SMOTE y sus variantes son herramientas esenciales para abordar el desafío de los datos desbalanceados. Su adecuada implementación en Scikit-Learn mejora significativamente la capacidad de los modelos para aprender de la clase minoritaria y ofrece un camino sólido hacia soluciones más equitativas y precisas en el aprendizaje supervisado.
Ensamblado de modelos para datos desbalanceados
El ensamblado de modelos es una estrategia eficaz para mejorar el rendimiento de los clasificadores en contextos de datos desbalanceados. Los modelos de ensamblado combinan múltiples estimadores de base para producir una predicción agregada, lo que puede aumentar la capacidad de generalización y mitigar el impacto del desbalance de clases.
Una técnica común es utilizar bosques aleatorios balanceados, donde se ajustan árboles de decisión sobre muestras bootstrap de los datos y se introducen modificaciones para abordar el desbalance. En Scikit-Learn, el parámetro class_weight='balanced'
asigna automáticamente pesos inversamente proporcionales a la frecuencia de las clases, equilibrando su influencia en el entrenamiento.
from sklearn.ensemble import RandomForestClassifier
# Crear un bosque aleatorio balanceado
modelo_rf = RandomForestClassifier(class_weight='balanced', random_state=42)
modelo_rf.fit(X_train, y_train)
Otra aproximación es el submuestreo bajo bolsa (bagging), donde se aplican técnicas de submuestreo al crear las muestras bootstrap. El BalancedBaggingClassifier de la biblioteca imbalanced-learn permite combinar el ensamble por bolsa con submuestreo aleatorio, mejorando la detección de la clase minoritaria.
from imblearn.ensemble import BalancedBaggingClassifier
from sklearn.tree import DecisionTreeClassifier
# Crear un clasificador con submuestreo bajo bolsa
modelo_bbc = BalancedBaggingClassifier(
base_estimator=DecisionTreeClassifier(),
sampling_strategy='auto',
replacement=False,
random_state=42
)
modelo_bbc.fit(X_train, y_train)
Los métodos de ensamblado por boosting también pueden adaptarse a datos desbalanceados. El RUSBoostClassifier combina el resampling aleatorio por submuestreo con AdaBoost, reduciendo el impacto de la clase mayoritaria en cada iteración del entrenamiento.
from imblearn.ensemble import RUSBoostClassifier
# Crear un clasificador RUSBoost
modelo_rusboost = RUSBoostClassifier(
base_estimator=DecisionTreeClassifier(max_depth=3),
n_estimators=100,
sampling_strategy='auto',
random_state=42
)
modelo_rusboost.fit(X_train, y_train)
El EasyEnsembleClassifier es otro método que genera varios conjuntos submuestreados de la clase mayoritaria y entrena un clasificador en cada uno junto con la clase minoritaria completa. Las predicciones finales se obtienen mediante la agregación de los resultados individuales.
from imblearn.ensemble import EasyEnsembleClassifier
# Crear un clasificador EasyEnsemble
modelo_easy = EasyEnsembleClassifier(
n_estimators=10,
sampling_strategy='auto',
random_state=42
)
modelo_easy.fit(X_train, y_train)
Es fundamental elegir el ensamblador adecuado según las características del problema y el conjunto de datos. Los parámetros como sampling_strategy
permiten controlar la proporción de submuestreo o sobremuestreo aplicado en cada estimador base, ofreciendo flexibilidad para adaptar el modelo al desequilibrio presente.
La combinación de técnicas de ensamble con métodos de sobremuestreo como SMOTE puede mejorar aún más el rendimiento. Por ejemplo, el BalancedRandomForestClassifier implementa un bosque aleatorio donde cada árbol se entrena en una muestra aleatoria con submuestreo de la clase mayoritaria.
from imblearn.ensemble import BalancedRandomForestClassifier
# Crear un bosque aleatorio balanceado
modelo_brf = BalancedRandomForestClassifier(
n_estimators=100,
sampling_strategy='auto',
random_state=42
)
modelo_brf.fit(X_train, y_train)
Al utilizar estos modelos, es imprescindible evaluar el rendimiento con métricas apropiadas para datos desbalanceados, como el recall, el F1-score o la curva ROC. De esta manera, se garantiza que el modelo no solo aprende a predecir la clase mayoritaria, sino que también es eficaz en la detección de la clase minoritaria.
El uso de pipelines en Scikit-Learn facilita la integración de estos ensambladores con técnicas de preprocesamiento y validación cruzada. Esto asegura un flujo de trabajo coherente y reproducible.
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
# Crear un pipeline con preprocesamiento y modelo
pipeline = make_pipeline(
StandardScaler(),
BalancedBaggingClassifier(
base_estimator=DecisionTreeClassifier(),
sampling_strategy='auto',
random_state=42
)
memory = None
)
pipeline.fit(X_train, y_train)
Los ensambladores permiten también ajustar los parámetros de los estimadores base para mejorar la adaptación a los datos desbalanceados. Por ejemplo, limitar la profundidad de los árboles o ajustar los criterios de división puede reducir el sobreajuste y mejorar la generalización.
Además, es posible combinar diferentes tipos de estimadores en un VotingClassifier para aprovechar las fortalezas de cada modelo. Aunque este enfoque no está específicamente diseñado para datos desbalanceados, la incorporación de modelos balanceados puede mejorar las predicciones.
from sklearn.ensemble import VotingClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.svm import SVC
# Crear un ensamble de votación con modelos balanceados
modelo_voting = VotingClassifier(
estimadores=[
('lr', LogisticRegression(class_weight='balanced', random_state=42)),
('svc', SVC(kernel='linear', class_weight='balanced', probability=True, random_state=42)),
('dt', DecisionTreeClassifier(class_weight='balanced', random_state=42))
],
voting='soft'
)
modelo_voting.fit(X_train, y_train)
En este ejemplo, se combinan diferentes algoritmos, cada uno ajustado para manejar el desbalance mediante el parámetro class_weight='balanced'
. El voto suave (voting='soft'
) utiliza las probabilidades de predicción para promediar los resultados.
Es esencial realizar una validación cruzada estratificada al evaluar modelos en datos desbalanceados. Esto garantiza que la proporción de clases se mantiene en cada partición, proporcionando estimaciones más fiables del rendimiento.
from sklearn.model_selection import cross_val_score, StratifiedKFold
# Definir validación cruzada estratificada
cv = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
# Evaluar el modelo con validación cruzada
scores = cross_val_score(modelo_brf, X_train, y_train, cv=cv, scoring='f1')
print(f"Puntuaciones F1 por fold: {scores}")
print(f"Puntuación F1 media: {scores.mean():.3f}")
La selección cuidadosa de las métricas y métodos de evaluación es clave para desarrollar modelos robustos en presencia de clases desequilibradas. Los ensambladores ofrecen herramientas poderosas para abordar este desafío, permitiendo mejorar la capacidad predictiva y generalización de los modelos en contextos complejos.
Evaluación en contextos desbalanceados
La evaluación de modelos en conjuntos de datos desbalanceados presenta retos únicos que requieren un enfoque cuidadoso. En escenarios donde una clase es significativamente más numerosa que otra, las métricas de evaluación tradicionales pueden ofrecer una visión distorsionada del rendimiento real del modelo.
Una métrica común como la exactitud (accuracy) puede resultar engañosa en estos contextos. Por ejemplo, si una clase representa el 95% de los datos, un modelo que siempre predice esa clase alcanzará un 95% de exactitud, pero será inútil para identificar la clase minoritaria. Por ello, es esencial emplear métricas que reflejen el rendimiento en ambas clases.
La matriz de confusión es una herramienta fundamental que muestra el número de verdaderos positivos, falsos positivos, verdaderos negativos y falsos negativos. A partir de ella, se pueden calcular métricas más informativas:
1 . Precisión (Precision): Proporción de verdaderos positivos entre todos los positivos predichos. Indica la exactitud de las predicciones positivas del modelo.
$$
\text{Precisión} = \frac{\text{Verdaderos Positivos}}{\text{Verdaderos Positivos} + \text{Falsos Positivos}}
$$
2. Exhaustividad (Recall): Proporción de verdaderos positivos entre todos los positivos reales. Mide la capacidad del modelo para encontrar todos los casos positivos.
$$
\text{Exhaustividad} = \frac{\text{Verdaderos Positivos}}{\text{Verdaderos Positivos} + \text{Falsos Negativos}}
$$
3. F1-score: Media armónica de la precisión y la exhaustividad. Equilibra ambas métricas en una sola.
$$
F1 = 2 \times \frac{\text{Precisión} \times \text{Exhaustividad}}{\text{Precisión} + \text{Exhaustividad}}
$$
En Scikit-Learn, estas métricas se pueden calcular fácilmente utilizando funciones específicas:
from sklearn.metrics import confusion_matrix, precision_score, recall_score, f1_score
# Supongamos que y_test son las etiquetas verdaderas y y_pred son las predicciones del modelo
matriz_confusion = confusion_matrix(y_test, y_pred)
print("Matriz de Confusión:")
print(matriz_confusion)
precision = precision_score(y_test, y_pred)
exhaustividad = recall_score(y_test, y_pred)
f1 = f1_score(y_test, y_pred)
print(f"Precisión: {precision:.2f}")
print(f"Exhaustividad: {exhaustividad:.2f}")
print(f"F1-score: {f1:.2f}")
Otra herramienta crucial es la curva ROC (Receiver Operating Characteristic) y el AUC (Area Under the Curve). La curva ROC representa la relación entre la tasa de verdaderos positivos y la tasa de falsos positivos a diferentes umbrales de clasificación. Un AUC cercano a 1 indica un modelo con excelente capacidad discriminativa.
from sklearn.metrics import roc_curve, roc_auc_score
import matplotlib.pyplot as plt
# Calcular probabilidades de predicción
y_score = modelo.predict_proba(X_test)[:, 1]
# Obtener valores para la curva ROC
fpr, tpr, thresholds = roc_curve(y_test, y_score)
auc = roc_auc_score(y_test, y_score)
# Graficar la curva ROC
plt.figure()
plt.plot(fpr, tpr, label=f"Curva ROC (AUC = {auc:.2f})")
plt.plot([0, 1], [0, 1], linestyle='--', color='red')
plt.xlabel('Tasa de Falsos Positivos')
plt.ylabel('Tasa de Verdaderos Positivos')
plt.title('Curva ROC')
plt.legend()
plt.show()
En casos de desbalance extremo, la curva Precision-Recall puede ser más informativa. Esta curva muestra la relación entre la precisión y la exhaustividad para diferentes umbrales, resaltando el rendimiento del modelo en la detección de la clase minoritaria.
from sklearn.metrics import precision_recall_curve, average_precision_score
# Obtener valores para la curva Precision-Recall
precision, recall, thresholds = precision_recall_curve(y_test, y_score)
ap = average_precision_score(y_test, y_score)
# Graficar la curva Precision-Recall
plt.figure()
plt.plot(recall, precision, label=f"Curva Precision-Recall (AP = {ap:.2f})")
plt.xlabel('Exhaustividad')
plt.ylabel('Precisión')
plt.title('Curva Precision-Recall')
plt.legend()
plt.show()
Es importante utilizar validación cruzada estratificada para garantizar que la proporción de clases se mantiene en cada partición. Esto se logra con el parámetro StratifiedKFold
de Scikit-Learn, que preserva la distribución original de las clases en cada fold.
from sklearn.model_selection import cross_val_score, StratifiedKFold
# Definir validación cruzada estratificada
cv = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
# Evaluar el modelo utilizando F1-score
scores = cross_val_score(modelo, X, y, cv=cv, scoring='f1')
print(f"Puntuaciones F1 por fold: {scores}")
print(f"Puntuación F1 media: {scores.mean():.2f}")
Otra palabra clave relevante es el ajuste de umbrales. En lugar de utilizar el umbral predeterminado de 0.5 para determinar las clases, es posible ajustarlo para equilibrar mejor la precisión y la exhaustividad según las necesidades específicas del problema.
# Ajustar el umbral de decisión
umbral = 0.3
y_pred_ajustado = (y_score >= umbral).astype(int)
# Recalcular métricas con el nuevo umbral
precision_ajustada = precision_score(y_test, y_pred_ajustado)
exhaustividad_ajustada = recall_score(y_test, y_pred_ajustado)
f1_ajustado = f1_score(y_test, y_pred_ajustado)
print(f"Precisión ajustada: {precision_ajustada:.2f}")
print(f"Exhaustividad ajustada: {exhaustividad_ajustada:.2f}")
print(f"F1-score ajustado: {f1_ajustado:.2f}")
El uso de la métrica Kappa de Cohen también puede ser útil, ya que mide el grado de concordancia entre las predicciones del modelo y las etiquetas reales, ajustando por concordancia aleatoria.
from sklearn.metrics import cohen_kappa_score
kappa = cohen_kappa_score(y_test, y_pred)
print(f"Kappa de Cohen: {kappa:.2f}")
Para una evaluación más completa, es recomendable utilizar el informe de clasificación que proporciona una visión general de múltiples métricas.
from sklearn.metrics import classification_report
reporte = classification_report(y_test, y_pred)
print("Informe de Clasificación:")
print(reporte)
En resumen, en contextos desbalanceados es crucial seleccionar métricas de evaluación que reflejen el rendimiento real del modelo en todas las clases. La utilización de herramientas como la curva ROC, el F1-score y la curva Precision-Recall permite una comprensión más profunda y precisa, facilitando la optimización y mejora continua del modelo.
Ejercicios de esta lección Preprocesamiento de datos desbalanceados
Evalúa tus conocimientos de esta lección Preprocesamiento de datos desbalanceados 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
Introducción Y Entorno
Introducción E Instalación
Introducción Y Entorno
Introducción Al Preprocesamiento De Datos
Preprocesamiento De Datos
Identificación Y Tratamiento De Valores Faltantes
Preprocesamiento De Datos
Escalado De Datos
Preprocesamiento De Datos
Normalización De Datos
Preprocesamiento De Datos
Codificación De Variables Categóricas
Preprocesamiento De Datos
Ingeniería De Características
Preprocesamiento De Datos
Selección De Características
Preprocesamiento De Datos
Extracción De Características
Preprocesamiento De Datos
Particionamiento De Datos
Preprocesamiento De Datos
Preprocesamiento De Datos Desbalanceados
Preprocesamiento De Datos
Introducción A La Regresión
Regresión
Regresión Lineal
Regresión
Regresión Knn Kneighborsregressor
Regresión
Regresión Svm Con Svr
Regresión
Regresión Con Árboles Decisiontreeregressor
Regresión
Regresión Con Algoritmos De Conjunto
Regresión
Introducción A La Clasificación
Clasificación
Clasificación Con Regresión Logística
Clasificación
Clasificación Knn Kneighborsclassifier
Clasificación
Clasificación Svm Con Svc
Clasificación
Clasificación Con Árboles Decisiontreeclassifier
Clasificación
Clasificación Con Algoritmos De Conjunto
Clasificación
Reducción De La Dimensionalidad Con Pca
Aprendizaje No Supervisado
Clustering Con Kmeans
Aprendizaje No Supervisado
Clustering Jerárquico
Aprendizaje No Supervisado
Clustering De Densidad Con Dbscan
Aprendizaje No Supervisado
Preprocesamiento De Textos Para Nlp
Nlp
Representación De Texto Y Extracción De Características
Nlp
Clasificación De Texto Con Scikit Learn
Nlp
Análisis De Sentimiento
Nlp
Técnicas Avanzadas De Extracción De Características
Nlp
Introducción Al Análisis De Series Temporales
Series Temporales
Preprocesamiento De Datos De Series Temporales
Series Temporales
Ingeniería De Características Para Series Temporales
Series Temporales
Transformación Y Escalado De Series Temporales
Series Temporales
Validación Y Evaluación De Modelos En Series Temporales
Series Temporales
Validación Y Evaluación De Modelos
Validación De Modelos
Técnicas De Validación Cruzada
Validación De Modelos
Métricas De Regresión
Validación De Modelos
Métricas De Clasificación
Validación De Modelos
Ajuste De Hiperparámetros
Validación De Modelos
Introducción A Pipelines
Pipelines Y Despliegue
Creación De Pipelines Básicos
Pipelines Y Despliegue
Preprocesamiento De Datos Con Pipelines
Pipelines Y Despliegue
Pipelines Y Validación Cruzada
Pipelines Y Despliegue
Pipelines Con Columntransformer
Pipelines Y Despliegue
Exportar E Importar Pipelines
Pipelines Y Despliegue
Objetivos de aprendizaje de esta lección
- Comprender los problemas causados por datos desbalanceados en modelos de aprendizaje automático.
- Aplicar técnicas de sobremuestreo y submuestreo para equilibrar conjuntos de datos.
- Implementar algoritmos avanzados de sobremuestreo como SMOTE y sus variantes en Scikit-Learn.
- Utilizar estrategias de ensamblado de modelos para mejorar el rendimiento en contextos desbalanceados.
- Evaluar modelos en situaciones de clases desequilibradas utilizando métricas apropiadas.