lección 6
Jueves B: la fuga oculta (el 96% es mentira)
El corazón del caso: cazas la columna que te chivaba el futuro, la quitas, el recall se desploma a 0,38, y ese modelo peor es el único honesto.
⏱ 55 min
## Jueves, 11:35. Tirando del hilo
Te has quedado con la frase de Raúl clavada: 0,93 de exhaustividad en un primer modelo de churn chirría. Vuelves a la pregunta del lunes y la aplicas columna por columna: ¿qué sabía yo de cada cliente en el momento de predecir? Antigüedad, cuota, consumo, tickets, contrato mensual... todas existen antes de la baja, todas son legítimas. Y entonces llegas a `gestion_retencion`, la columna rara que apuntaste el primer día y que Bea no supo explicarte del todo. Te paras a pensar cuándo se pone a 1, y ahí cae todo: retención solo interviene sobre un cliente cuando ya está dándose de baja o a punto. Esa columna no describe al cliente antes de la baja: describe que la empresa ya sabía que se iba. Es información del futuro disfrazada de feature. La frasecita de Bea, esa a la que nadie hacía caso, llevaba razón todo el tiempo: una columna te estaba chivando el futuro.
Esto que acabas de encontrar tiene nombre y es, probablemente, el error que más modelos mata en producción: se llama fuga de datos (en inglés, data leakage). Ocurre cuando una feature contiene, de forma directa o indirecta, información que solo se conoce después del desenlace que intentas predecir. El modelo «aprende» esa feature, da unos números espectaculares en tus pruebas, y luego, en el mundo real, falla estrepitosamente, porque esa información no existe cuando toca predecir de verdad. Es traicionera porque no da ningún error: todo compila, todo corre, las métricas salen preciosas. La única defensa es la pregunta de Raúl, hecha a tiempo, columna por columna. Lo de esta tarde completa `src/04_evaluar.py`, el fichero de la verdad honesta: aquí quitas la fuga y aceptas las métricas reales.
Si todavía dudas de que esa columna fuera el problema, hay una forma de verlo que no engaña: mirar cuánto peso le dio el modelo a cada feature. Como la regresión logística se puede explicar —esa era su gracia—, puedes preguntarle qué columna pesó más en sus decisiones. Y lo que ves es desproporcionado: `gestion_retencion` tiene un peso que aplasta al de todas las demás juntas. El modelo apenas miraba la antigüedad, la cuota o el consumo; estaba casi todo el rato leyendo esa única columna, porque era la que mejor «predecía» la baja (claro: era un reflejo de la baja). Un peso así de dominante en una sola feature es, en sí mismo, una señal de alarma: cuando una columna lo explica casi todo, pregúntate si no será que esa columna ES la respuesta disfrazada.
Y hay una segunda razón, aún más contundente, por la que `gestion_retencion` no puede estar en el modelo: ni siquiera estaría disponible. Fíjate en que el fichero de clientes activos de hoy —`clientes_hoy`, sobre el que tienes que construir la lista— ni siquiera trae esa columna. Tiene sentido: sobre los clientes que se van a ir, retención todavía no ha actuado, porque todavía no sabe que se van (de hecho, averiguarlo es tu trabajo). Así que la columna que inflaba tu modelo no solo es trampa: es que el día que fueras a usarlo de verdad, esa casilla estaría vacía para todo el mundo. Un modelo que depende de ella es un modelo que no se puede usar.
## Quitar la columna y reentrenar: el momento de la verdad
La prueba definitiva es sencilla: quita `gestion_retencion`, reentrena el modelo exactamente igual, y mira qué pasa con las métricas. Y lo que pasa es un terremoto. El acierto baja del 99% al 96%. Y la exhaustividad, que era un 0,93 que parecía magia, se desploma a 0,38. El modelo, sin la columna que le chivaba el futuro, caza a menos de 4 de cada 10 clientes que se van. En números absolutos, de los 133 que de verdad se van en la prueba, el modelo honesto solo caza 50. A primera vista parece que has roto el modelo, que lo has empeorado tú mismo. La reacción natural es querer volver a meter la columna. No lo hagas: lo que acabas de hacer es arreglarlo.
Y ahora el golpe que ordena todo el caso. Ese 96% honesto, puesto al lado de la línea base, cuenta la verdad del problema: un modelo que dijera «no se va nadie» acierta el 95%, así que tu modelo honesto, con todas sus features legítimas, está a UN punto de no hacer nada. El 96% es, para este problema, casi una mentira: suena a modelo decente y apenas supera a no mirar los datos. El 99% de ayer era una mentira más grande todavía, porque encima leía el futuro. Esta es la foto real de tu primer modelo de churn: acierta un 96% que vale poco, y caza a menos de 4 de cada 10 de los que de verdad importan. Incómodo, pero verdadero.
1Tú 12:102Raul, era gestion_retencion. La quito y el recall se cae de 0,933a 0,38. Parece que he roto el modelo.45Raúl 12:146No lo has roto: lo has arreglado. Esa columna solo se enciende7cuando retencion ya actuo, o sea cuando el cliente ya estaba de8salida. El modelo no predecia la baja, la LEIA.910Raúl 12:15110,38 real vale infinitamente mas que 0,93 que no existe fuera de12tu portatil. Con el espejismo mandabas a Lola a llamar a gente que13el sistema YA habia marcado. Con el honesto, a gente a la que14todavia llegas a tiempo. Ese es tu modelo. Enhorabuena.
Raúl cierra el círculo: el 0,38 honesto es el primer resultado de verdad de la semana.
Esa es la frase que te llevas de toda la semana: un 0,38 que existe vale más que un 0,93 que solo vive en tu portátil. Un recall de 0,38 no es un fracaso: es el punto de partida real sobre el que mejorar, y es útil ya, porque retención no puede llamar a todos de todas formas; lo que necesita es que los primeros de la lista sean de verdad los de más riesgo, y eso el modelo honesto lo hace. El modelo del 99% habría gastado el recurso escaso —las llamadas— en gente que el sistema ya tenía fichada o que ya estaba de salida: ni siquiera habría salvado a nadie, porque esos clientes ya estaban identificados por otra vía. El honesto, en cambio, señala a gente a la que todavía se puede retener. Un número más bajo, pero que sirve.
Hay un momento raro cuando descubres algo así, y conviene que lo nombres para gestionarlo: no es alegría, es más bien un nudo en el estómago. Acabas de encontrar que la conclusión de Lola —«dame la lista, confírmame lo que ya sé»— se apoyaba en un modelo que leía el futuro, y mañana tienes que contarlo delante de Ignacio. El impulso humano es suavizarlo, buscar una forma de que todo el mundo tenga un poco de razón. Resiste ese impulso, pero cuida la forma. Bea, que ha visto la pantalla por encima de tu hombro, te da el consejo que importa:
1Bea 12:222lo encontraste eh 👏3llevo diciendo lo de las columnas que chivan el futuro desde que4entraste y nadie miraba5un consejo para manana: no se lo sueltes a Lola a bocajarro delante6de Ignacio. diselo antes en privado, con el grafico. la gente encaja7mucho mejor una mala noticia si no la pillan en publico8y cuentalo con el dato por delante, no con "lola se equivoco". el9numero manda, no tu
Bea, la única que sospechaba, confirma el hallazgo y da el consejo de cómo contarlo.
Nunca juzgues un modelo por lo bien que suena un número, sino por si ese número existirá cuando toque predecir de verdad. Un 0,93 de recall construido sobre una columna que no estará disponible en producción vale cero: peor que cero, porque te da confianza falsa y te lleva a tomar una decisión equivocada con convicción. Un 0,38 honesto, medido sobre features que sí existirán, es un cimiento real sobre el que construir.
## Por qué nadie lo había visto antes
Vale la pena entender por qué una fuga así puede llevar meses en una empresa sin que nadie la cace, porque te dice dónde mirar en tu próximo proyecto. La columna `gestion_retencion` no es un error: para el equipo de Lola es un dato útil y correcto, que les sirve para su reporting (saber sobre cuántos clientes han actuado). El problema no está en la columna, está en usarla para una cosa para la que no sirve: predecir. Y ese salto —de «dato correcto para una cosa» a «feature tramposa para otra»— no lo ve el que generó la columna, porque él la usa bien; solo lo ve quien se pregunta, al meterla en un modelo, en qué momento se rellena. Las fugas casi nunca son datos malos: son datos buenos usados en el momento equivocado del tiempo.
Hay una idea general detrás de todo el jueves, y conviene que la nombres porque es de las más potentes del oficio: un modelo honesto solo puede usar información que existiría ANTES del desenlace que predice. Dicho así suena obvio, y sin embargo es el error que más modelos mata en producción, porque la información del futuro se cuela disfrazada de mil formas: una columna que se rellena después (como aquí), un dato que se actualiza con el tiempo y del que coges el valor «de hoy» en vez del «de entonces», una media calculada sobre todo el histórico incluyendo lo que vino después. La defensa es siempre la misma pregunta, hecha columna por columna: ¿esta casilla ya estaría rellena en el instante en que tengo que predecir? Si la respuesta es «no», da igual lo bien que correlacione: es una fuga.
## Blindar el hallazgo antes de que lo ataquen
Hay una asimetría que conviene conocer, porque cambia cómo trabajas cuando un hallazgo incomoda a alguien. Cuando tu número confirma lo que todos esperan, nadie lo audita: Lola habría cogido el 99% sin pedir ni una comprobación. Cuando lo desmiente, en cambio, lo van a mirar con lupa, y más de uno buscará el fallo en tu cálculo antes que en su idea. Por eso, con un hallazgo así, no basta con tener razón: hay que poder demostrarla sin fisuras. Lo que has hecho hoy en el orden correcto es exactamente eso: no te has quedado en «quito la columna y baja el recall», has comprobado también que la columna ni siquiera existe en los clientes de hoy, has mirado qué peso le daba el modelo, y vas a poder enseñar la matriz antes y después. No es exceso de celo: es blindar el hallazgo antes de llevarlo a una sala donde a nadie le gusta la respuesta.
La frase de Raúl del lunes cobra aquí todo su sentido: un número que sabes de dónde sale se puede defender. El 99% no sabías de dónde salía —de hecho salía de una columna que no habías mirado con cuidado—, y por eso era indefendible en cuanto alguien tirase del hilo. El 0,38, en cambio, lo puedes sostener casilla a casilla: estas son las features, todas existen al predecir, este es el reparto de la matriz, esta es la línea base contra la que se compara. Esa trazabilidad es lo que convierte una conversación tensa («tú contra Lola») en una conversación técnica («todos contra el problema del modelo tramposo»). El dato bien construido desactiva la pelea.
Consejo de senior: cuando quites una fuga de datos y veas desplomarse tus métricas, no has empeorado el modelo: has dejado de engañarte. Es uno de los momentos más contraintuitivos del oficio, y distingue a quien ha madurado como científico de datos de quien aún persigue el número bonito. Celebra el 0,38 honesto: es tu primer resultado de verdad, y es el único que puedes defender delante de Ignacio sin que se te caiga la cara mañana.
Tienes el hallazgo y lo tienes blindado. Pero un hallazgo que se queda en tu portátil no cambia nada. Mañana es viernes, y a las doce te sientas delante de Ignacio, que no quiere ver tu código ni tus matrices: quiere saber si puede fiarse de la lista y a cuánta gente salva su equipo con ella. Toca convertir la verdad incómoda de hoy —el 99% era mentira, el modelo honesto caza a 4 de cada 10— en algo que se entienda en cinco segundos y mueva una decisión. Descubrir la verdad era la mitad del trabajo; que alguien la entienda y actúe es la otra mitad, y la que de verdad decide si tu semana ha servido para algo.
## 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.