lección 6
Jueves: reequilibrar y elegir el umbral
La cura: con class_weight=balanced el recall salta de 0,009 a 0,71, la accuracy baja y aparecen falsas alarmas; y el umbral es una palanca de negocio.
⏱ 55 min
## Jueves, 11:35. «¿Cómo le decimos que esos pocos importan más?»
Ya sabes que tu modelo caza a 3 de 329. Álvaro cierra el diagnóstico y abre la cura con una pregunta: «El modelo no es tonto: es que acertar a los que se quedan le sale gratis y hay nueve veces más. Así que ignora a la clase rara. ¿Cómo le decimos "esos pocos me importan MÁS"?». Lo piensas y aciertas: pesando más a la clase minoritaria. «Eso es», responde. «En scikit-learn se hace con `class_weight='balanced'`. Reentrena con eso y vuelve a medir.»
La idea es sencilla y potente. Por defecto, cada error cuenta lo mismo: equivocarse con un socio que renueva pesa igual que equivocarse con uno que no. `class_weight='balanced'` cambia esa regla: le dice al modelo que un error sobre la clase rara cuesta mucho más, en proporción a lo rara que es. De pronto, al modelo ya no le sale gratis callar sobre los que se van: cada uno que se le escapa le duele. Y cambia de estrategia: empieza a marcar a muchos más socios como «no renueva». Reentrenas, y los números dan un vuelco.
El recall sube de 0,009 a 0,711: el modelo pasa de cazar 3 de 329 a cazar 234. A cambio, la accuracy baja a 0,666 y aparecen 907 falsas alarmas: socios que el modelo marca como riesgo y que en realidad iban a renovar. Y aquí está la parte que cuesta aceptar, pero que es la lección entera: eso no es haber estropeado el modelo. Un socio recuperado vale mucho más que una llamada de cortesía a alguien que iba a quedarse igual. El modelo del 90% cazaba a 3 de los que se iban; el reequilibrado caza a 234. ¿Cuál le darías a fidelización? El segundo, sin dudarlo. Y eso, como insiste Álvaro, no es una decisión técnica: es de negocio.
## La misma idea, a mano: remuestrear con pandas
Pesar la clase rara con `class_weight` no es la única forma de decirle al modelo «hazle caso a los que se van». Hay otra, más artesanal, que ayuda a entender qué está pasando por debajo: remuestrear a mano. En vez de cambiar los pesos, cambias los datos. Submuestrear consiste en quedarte con todos los socios que no renuevan y una muestra igual de grande de los que sí, usando `df.sample()`, de modo que el entrenamiento vea las dos clases a partes iguales. El modelo, al ver tantos ejemplos de cada clase, deja de tener el atajo de callar. El efecto sobre el recall es parecido al de `class_weight`. Son dos caminos a la misma meta: igualar la voz de la clase rara.
Para reequilibrar clases NO uses SMOTE ni la librería imbalanced-learn (imblearn): no funcionan en el navegador donde corre tu código. En este proyecto el desbalanceo se trata solo con class_weight='balanced' de scikit-learn o remuestreando a mano con df.sample() de pandas. Las dos herramientas te sobran para este caso, y las dos corren sin problemas en el motor.
## El remate: el umbral es una palanca de negocio
Falta la última pieza, y es la que convierte un modelo en una herramienta de negocio. El modelo da una probabilidad por socio, y por defecto marca «no renueva» si pasa de 0,5. Pero ese 0,5 no es sagrado. Si lo bajas, pescas más socios en riesgo —el recall sube— a costa de más falsas alarmas —la precisión baja—. Si lo subes, al revés: una lista más corta y fina, pero se te escapan más. Esa curva de intercambio entre precisión y recall según el umbral es la curva precision-recall, y su área es el PR-AUC que ya calculaste. Lo nuevo hoy es entender que elegir el punto de la curva —el umbral— no lo decide el modelo: lo decide Marisol, según cuántas llamadas puede hacer su equipo.
Álvaro cierra el día: «Resumen de lo que has descubierto hoy, y vale más que el modelo entero. El 90% era un espejismo del desbalanceo. Reequilibrando, el modelo caza de verdad a los que se van. Y el umbral no es un número técnico: es una palanca entre no se me escapa nadie y no molesto a quien iba a renovar. Esa palanca la mueve Marisol, no tú.» Y tú lo rematas: «Entonces el modelo bueno no es el que más acierta. Es el que coge a los pocos que importan.» Ahí lo tienes. Eso es lo que lleváis el viernes.
Sigues con datos/tabla_modelo.csv y el reparto de siempre (test_size=0.2, random_state=42, stratify=y). Hoy cierras src/04_evaluar.py (reequilibrado, remuestreo y curva PR) y abres src/05_prediccion.py. Recuerda: el desbalanceo se trata con class_weight='balanced' o df.sample(), nunca con SMOTE/imblearn.
volver a la visión del caso y descargar los datasets## comentarios
Reporta erratas, ayuda a otros o comparte tu opinión. Sé constructivo.
Inicia sesión para comentar y responder.
cargando comentarios...
Regístrate para guardar tu progreso.