Machine Learning — Módulo 11: problemas del mundo real — desbalance, interpretabilidad y sesgo
Módulo avanzado del Curso de Machine Learning: lo que los tutoriales no cuentan. Datos desbalanceados (fraude al 0,1%) con class_weight, resampling y SMOTE, las métricas correctas (recall, PR-AUC en vez de accuracy), interpretabilidad con SHAP, sesgo y fairness, y el data leakage que aparece recién en producción.
☰ Índice del contenido
En el módulo 10 salimos del mundo supervisado hacia el clustering y PCA. Ahora volvemos al supervisado, pero al que de verdad te espera en el trabajo — no el de los datasets limpios y balanceados de los tutoriales. En el mundo real el fraude es el 0,1% de las transacciones, el jefe te pregunta “¿y por qué el modelo rechazó a ese cliente?”, el área legal quiere saber si discrimina, y una feature que funcionaba perfecto en tu notebook simplemente no existe cuando el modelo tiene que predecir en vivo. Este módulo es sobre esos cuatro golpes de realidad.
La tesis del módulo
Un modelo con 99% de accuracy en detección de fraude puede ser basura absoluta: predice “no fraude” siempre y acierta el 99% porque el fraude es el 1%. En el mundo real la métrica engaña, el modelo debe explicarse, puede discriminar sin que lo notes, y features que existían al entrenar desaparecen al predecir. El oficio empieza donde termina el tutorial.
Datos desbalanceados: cuando una clase es rarísima
Los datos desbalanceados son aquellos donde una clase es muchísimo más común que otra. El caso canónico: fraude bancario, donde el 99,9% de las transacciones son legítimas y el 0,1% es fraude. El modelo tiene una salida tramposa: predecir “no fraude” siempre. Acierta el 99,9% de las veces y no detecta ni un solo fraude. Inútil, pero con accuracy espectacular.
Primer arreglo: las métricas correctas
Con desbalance, la accuracy miente. Las métricas que importan (las vimos en el módulo 4, ahora entiendes por qué existen):
- Recall (sensibilidad): de todos los fraudes reales, ¿cuántos atrapé? Es la métrica reina cuando el costo de no detectar es alto.
- PR-AUC (área bajo la curva precision-recall): resume el equilibrio entre atrapar fraudes (recall) y no llenar de falsas alarmas (precision). En desbalance fuerte es más honesta que la ROC-AUC, porque no se deja engañar por la montaña de negativos.
Sin desbalance en la cabeza:
99,9% legítimas ██████████████████████████████████
0,1% fraude █
"predigo NO FRAUDE siempre" ──► accuracy 99,9%
──► recall de fraude = 0%
(no atrapó ni uno)
Segundo arreglo: reequilibrar
Tres técnicas para que el modelo no ignore la clase rara:
class_weight: le dices al modelo que equivocarse en la clase rara cuesta más. No inventa datos; solo pondera. Es lo primero que hay que probar, casi gratis.- Resampling: cambiar la proporción. Undersampling (tirar ejemplos de la clase común) o oversampling (duplicar los de la rara).
- SMOTE (Synthetic Minority Over-sampling Technique): en vez de duplicar los ejemplos raros, crea ejemplos sintéticos nuevos interpolando entre los reales de la clase minoritaria. Da más variedad que el simple duplicado.
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import classification_report, average_precision_score
# Lo más simple y a menudo suficiente: penalizar el error en la clase rara.
modelo = RandomForestClassifier(
n_estimators=300,
class_weight="balanced", # ajusta pesos según la frecuencia de cada clase
random_state=42,
)
modelo.fit(X_train, y_train)
proba = modelo.predict_proba(X_test)[:, 1] # probabilidad de fraude
pred = modelo.predict(X_test)
print(classification_report(y_test, pred)) # mira el recall, no accuracy
print("PR-AUC:", average_precision_score(y_test, proba)) # la métrica honesta
Ojo: SMOTE y el resampling se aplican solo al conjunto de entrenamiento, y dentro del pipeline de CV (módulo 9). Si generas ejemplos sintéticos antes de partir train/test, contaminas el test con datos derivados de sí mismo: leakage. Nunca hagas SMOTE sobre los datos completos.
| Técnica | Qué hace | Costo | Riesgo |
|---|---|---|---|
class_weight | Pondera el error de la clase rara | Casi cero | A veces no basta |
| Undersampling | Tira ejemplos de la clase común | Pierdes datos | Descartas información útil |
| Oversampling | Duplica ejemplos de la clase rara | Barato | Overfitting a los repetidos |
| SMOTE | Crea ejemplos sintéticos nuevos | Medio | Puede inventar casos poco realistas |
Interpretabilidad con SHAP
Los modelos potentes (Random Forest, XGBoost) son cajas negras: aciertan, pero no dicen por qué. En banca, salud o cualquier decisión auditable, eso no alcanza — necesitas explicar cada predicción. SHAP (SHapley Additive exPlanations) explica cuánto aportó cada feature a una predicción concreta: te dice que este cliente fue marcado como fraude porque el monto sumó +0,4, el país sumó +0,2 y su antigüedad restó −0,1.
Es clave para dos cosas: auditar el modelo (verificar que decide por razones sensatas y no por una feature espuria) y explicarle al cliente o al regulador por qué se tomó una decisión.
import shap
modelo = RandomForestClassifier(n_estimators=300, random_state=42)
modelo.fit(X_train, y_train)
# TreeExplainer es el explainer optimizado para modelos de árboles
# (Random Forest, XGBoost). Exacto y rápido para ellos.
explainer = shap.TreeExplainer(modelo)
# Llamar al explainer devuelve un objeto Explanation. Para un
# clasificador de sklearn tiene forma (filas, features, clases):
# nos quedamos con la clase 1 (fraude) con el índice [..., 1].
explicacion = explainer(X_test)
fraude = explicacion[:, :, 1]
# Importancia global: qué features mueven al modelo en promedio
shap.plots.beeswarm(fraude)
# Explicación de UNA predicción concreta (la fila 0):
# cuánto empujó cada feature esa decisión específica
shap.plots.waterfall(fraude[0])
Contribuciones SHAP a UNA predicción (cliente X)
base (promedio) │████ 0,30
monto alto │ ████████ +0,25 a fraude
país distinto │ ████ +0,12 a fraude
hora normal │ ██ -0,05 a legítimo
antigüedad alta │ ████ -0,10 a legítimo
└───────────────────►
predicción final: 0,52 ──► marcado como fraude
Sesgo y fairness
Un modelo aprende de datos históricos, y la historia trae sus sesgos. Fairness (equidad) es medir y controlar que el modelo no discrimine sistemáticamente a un grupo (por género, edad, comuna, etc.). Un modelo de scoring crediticio entrenado con datos donde a cierto grupo se le negó crédito por prejuicio, aprenderá a negárselo también — con apariencia de objetividad matemática.
Lo mínimo responsable: medir el rendimiento del modelo por subgrupo. Si tu recall es 90% para un grupo y 60% para otro, tienes un problema de equidad aunque la métrica global se vea bien. SHAP ayuda a auditar: si una feature sensible (o un proxy de ella, como la comuna) domina las decisiones, es una alerta roja.
Ojo: “el modelo es objetivo porque es matemático” es una de las creencias más peligrosas del oficio. El modelo reproduce los sesgos de sus datos con eficiencia industrial. Medir fairness no es opcional en decisiones que afectan personas.
Data leakage en producción
El módulo 9 habló del leakage al preprocesar fuera del CV. Hay una forma más traicionera que aparece recién en producción: usar una feature que no existe al momento real de predecir.
Ejemplo clásico: entrenas un modelo para predecir si un paciente será hospitalizado, y entre las features va “cantidad de días hospitalizado”. En tu tabla histórica ese dato está y el modelo lo ama — predice perfecto. Pero al momento de predecir en vivo, para un paciente que aún no ingresa, ese dato no existe: se conoce después del hecho que quieres predecir. Tu modelo brillante en el notebook falla en producción.
EN EL NOTEBOOK (datos históricos)
┌──────────────────────────────┐
│ edad, síntomas, │
│ días_hospitalizado ◄── FUGA │
│ (dato del futuro) │
└───────────────┬──────────────┘
▼
accuracy 98% (mentira)
EN PRODUCCIÓN (predecir en vivo)
┌──────────────────────────────┐
│ edad, síntomas, │
│ días_hospitalizado = ??? │
│ (aún no existe todavía) │
└───────────────┬──────────────┘
▼
el modelo se cae
La defensa: por cada feature pregúntate “¿este dato existe en el instante exacto en que necesito predecir?”. Si la respuesta es “no, se sabe después”, esa feature filtra el futuro y hay que sacarla, por muy predictiva que se vea.
Errores comunes
- Reportar accuracy en problemas desbalanceados. El error que este módulo grita. 99% de accuracy con la clase rara al 1% puede significar cero detecciones. Usa recall y PR-AUC.
- Hacer SMOTE sobre todos los datos. Genera sintéticos con información del test y filtra. SMOTE va solo en el train, dentro del pipeline de CV.
- Confiar en una caja negra sin auditarla. Un modelo que acierta por la razón equivocada (una feature espuria) explota apenas cambie el contexto. SHAP existe para detectar eso.
- Asumir que el modelo es neutral. Reproduce los sesgos de sus datos. Si no mides fairness por subgrupo, estás desplegando discriminación sin saberlo.
- No preguntarse cuándo existe cada feature. El leakage de producción es el que más duele: pasa todos los tests offline y se cae en vivo. Audita el momento de disponibilidad de cada dato.
- Perseguir una sola métrica. Recall al 100% es fácil: marca todo como fraude. La gracia es el equilibrio con la precisión; por eso PR-AUC y no un número suelto.
La frase para llevarse
“En el mundo real la accuracy engaña, la caja negra hay que abrirla, el modelo puede discriminar sin avisar, y la feature que te hace campeón en el notebook puede no existir cuando toca predecir de verdad.”
Qué viene
Módulo 12: del notebook a producción. El cierre del curso. Cómo sacar tu modelo del cuaderno y ponerlo a trabajar: serializar el pipeline completo con joblib, exponerlo como API o batch, versionar datos y modelo, y el puente hacia MLOps — monitorear en producción, detectar cuando el modelo se degrada solo (drift) y reentrenar.
Material relacionado
Preguntas sobre este curso
Regístrate gratis para hacer preguntas y guardar tu progreso.
✉ Entérate de lo nuevo
Recibe un aviso cuando publique nuevos cursos, workshops o investigaciones. Sin spam.