Saltar al contenido

lección 5

Datos con fecha: el corte que no es un sorteo

Con datos con fecha, partir al azar es entrenar con el futuro para predecir el pasado: el corte tiene que ser temporal, no un sorteo.

⏱ 55 min

Todo lo que has visto hasta ahora reparte los ejemplos al azar: barajas la baraja y cortas. Hay una suposición escondida en ese gesto, y conviene sacarla a la luz, porque cuando no se cumple lo rompe todo. La suposición es que el orden de los ejemplos no significa nada: que da igual cuál llegó antes y cuál después, porque son intercambiables. Para muchos problemas es verdad. Pero hay un tipo de datos muy común donde el orden es lo más importante que hay, y donde barajar al azar es, literalmente, hacer trampa: los datos que tienen fecha.

Ventas por día, usuarios que se registran a lo largo del tiempo, mediciones de un sensor cada hora, pedidos, visitas, cualquier cosa que ocurra y quede sellada con un momento. En todos esos casos sueles querer predecir hacia delante: a partir de lo que ha pasado hasta hoy, estimar lo que pasará mañana. Y ahí la pregunta de validación cambia de forma, porque en el mundo real nunca tendrás datos del futuro para entrenar. El examen honesto tiene que respetar esa frontera, y el reparto al azar la pisotea sin que te des cuenta.

Estos datos tienen un nombre, series temporales, y una propiedad que los hace especiales: el orden no es un adorno, es información. En una tabla de fotos de perros y gatos, si cambias el orden de las filas no pierdes nada; cada foto es un ejemplo independiente que vale lo mismo venga antes o después. En una serie de ventas diarias, el orden lo es todo: las ventas de hoy dependen de la tendencia de las últimas semanas, de la estación del año, de si ayer fue festivo. Cada día está enganchado a los que lo rodean. Barajar una serie temporal es como barajar las páginas de una novela: cada frase sigue siendo correcta, pero la historia se destruye, porque lo que daba sentido a cada página era su posición respecto a las demás. El azar, que para datos independientes es lo correcto, para series temporales es demoledor precisamente porque borra el orden, que era lo importante.

## Por qué barajar es hacer trampa

Imagina que tienes las ventas diarias de dos años y quieres un modelo que las prediga. Si partes al azar, el conjunto de entrenamiento acaba con días repartidos por todo el calendario, y el de prueba también: en el entrenamiento te caen días de enero, de agosto, del año pasado y de este, mezclados; y en la prueba, otros tantos, también mezclados. El problema es que entre los días de entrenamiento hay fechas posteriores a algunas de las fechas que vas a predecir. Estás entrenando el modelo con información del futuro para que luego prediga el pasado. En producción eso es imposible: el martes no tienes los datos del jueves. Pero en tu reparto al azar sí los tienes, y el modelo los aprovecha sin que tú lo sepas.

El efecto es demoledor y silencioso: el modelo parece buenísimo. Como entre sus datos de entrenamiento hay días muy cercanos a los que tiene que predecir (el día de antes, el de después, la misma semana), le resulta facilísimo acertar; básicamente interpola entre fechas que ya conoce. Tu medida de acierto sale espectacular. Y es completamente falsa, porque esa cercanía temporal entre entrenamiento y prueba no existirá nunca cuando el modelo trabaje de verdad, prediciendo días que todavía no han ocurrido. Has medido una tarea mucho más fácil que la real, y el número que sacaste no sirve para nada.

La palabra clave que acaba de aparecer, interpolar, merece explicarse, porque es la raíz del engaño. Interpolar es rellenar un hueco entre dos valores que ya conoces: si sabes cuánto se vendió el lunes y cuánto el miércoles, adivinar el martes es fácil, está en medio y las ventas no suelen pegar saltos bruscos de un día para otro. Extrapolar, en cambio, es estimar más allá de lo que conoces: si solo sabes lo de hasta el miércoles, adivinar el viernes de la semana siguiente es mucho más difícil, porque te alejas de lo conocido hacia terreno que no has visto. El reparto al azar convierte, sin que te des cuenta, un problema de extrapolación (predecir el futuro, que es lo que harás en producción) en uno de interpolación (rellenar huecos entre fechas que ya tienes). Y como interpolar es muchísimo más fácil, tu número sale inflado. La tarea que mediste no es la tarea que vas a hacer.

Hay una forma aún más clara de ver por qué esto es trampa, que es imaginar la escena en producción. El día que tu modelo esté funcionando de verdad, tendrá que predecir las ventas del jueves usando solo lo que ocurrió hasta el miércoles, porque el jueves todavía no ha pasado y sus datos no existen. Jamás, bajo ninguna circunstancia, tendrá acceso a datos de fechas posteriores a la que predice: el futuro no se ha escrito aún. Si en tu validación le dejaste entrenar con días posteriores a los que examinaba, le concediste un superpoder que en la realidad no tendrá nunca, el de ver el futuro. Medir con un superpoder que luego le quitas es medir a otro modelo distinto del que vas a desplegar. Por eso el número no sirve: midió a un adivino con bola de cristal, y el que trabajará es uno sin ella.

Al barajar, en el entrenamiento caen fechas posteriores a las que vas a predecir. El modelo usa el futuro para acertar el pasado, algo que jamás podrá hacer en producción.

## El corte temporal: entrena con lo antiguo, examina con lo reciente

La forma honesta de partir datos con fecha no es un sorteo: es un corte en el tiempo. Ordenas los ejemplos por su fecha, de los más antiguos a los más recientes, y eliges un momento de corte. Todo lo anterior al corte es el entrenamiento; todo lo posterior, la prueba. Entrenas el modelo con el pasado y lo examinas con el futuro, exactamente igual que tendrá que trabajar cuando esté en producción: con lo que ya ocurrió, predecir lo que viene. No hay ni un solo día del entrenamiento que sea posterior a un día de la prueba. La frontera entre pasado y futuro, que el sorteo rompía, queda intacta.

Fíjate en que este corte no baraja nada, y eso es lo correcto, no una pereza. Cuando los ejemplos son independientes se baraja antes de cortar, precisamente para que los distintos tipos queden repartidos de forma pareja entre los montones. Con datos que tienen fecha, barajar es justo lo que no quieres, porque mezclaría pasado y futuro: aquí el reparto desigual (todo lo antiguo a un lado, todo lo reciente al otro) no es un defecto, es el objetivo. Es un buen ejemplo de que las reglas de la validación no se aplican de memoria: barajar es correcto para datos independientes y prohibido para series temporales, y lo que decide cuál de las dos cosas haces es entender qué son tus datos, no repetir un gesto por costumbre.

Este corte reproduce la tarea real, y por eso su número es honesto aunque casi siempre sea peor. Y es una buena noticia que sea peor. Significa que estás midiendo la dificultad de verdad: predecir hacia delante, con datos que de verdad no has visto porque todavía no habían ocurrido, extrapolando más allá de lo conocido en vez de rellenar huecos entre fechas que ya tenías. Un modelo que da un 95% con corte al azar y un 70% con corte temporal no es que haya empeorado: es que el 95% era mentira y el 70% es la verdad. Preferir el 70% honesto al 95% falso es toda la lección.

Esta idea del corte temporal se extiende a todo lo demás que ya sabes. ¿Recuerdas los tres montones y la validación? Con datos que tienen fecha, el mismo principio se aplica a los tres: no solo la prueba va al final del calendario, también la validación va después del entrenamiento y antes de la prueba. Entrenas con el periodo más antiguo, eliges tu modelo validando sobre un periodo intermedio, y examinas sobre el periodo más reciente, todo respetando el orden del tiempo de principio a fin. La frontera pasado-futuro no se cruza en ninguno de los tres cortes. Es la misma disciplina de siempre, con una regla extra: el reloj manda, y nada que ocurra después puede usarse para predecir algo que ocurrió antes.

Vale la pena nombrar un detalle que a veces se pasa por alto incluso haciendo bien el corte: la fuga también puede colarse por una variable, no solo por el reparto. Si entre tus columnas tienes algo que resume el futuro (por ejemplo, un promedio de ventas calculado sobre todo el periodo, incluidas fechas posteriores a la que predices), ese promedio lleva información del futuro dentro aunque el corte de los datos sea impecable. Construir las variables respetando el tiempo es tan importante como partir respetando el tiempo: cada variable de una fila de cierta fecha solo puede usar información disponible hasta esa fecha, nunca posterior. Esto enlaza directamente con la fuga de datos que verás a continuación, pero conviene plantar la semilla aquí: con fechas de por medio, el futuro se puede colar por dos puertas, el reparto y las variables, y las dos hay que vigilarlas.

El corte temporal entrena con lo antiguo y examina con lo reciente. Reproduce la tarea real, y por eso su número es creíble aunque suela ser más bajo.
El corte al azar da un error pequeño porque mide una tarea más fácil que la real. El corte temporal da un error mayor, y es el que de verdad verás en producción.

Antes de partir cualquier conjunto de datos, pregúntate: ¿hay una fecha de por medio y voy a predecir hacia el futuro? Si la respuesta es sí, el reparto al azar está prohibido: el corte tiene que ser temporal. Esta pregunta es un reflejo que te ahorrará el error más caro de esta familia, porque el reparto al azar sobre datos con fecha no da ningún aviso: funciona, compila, y te regala un número precioso y falso.

Esa pregunta parece trivial, pero se olvida con una facilidad asombrosa, y casi siempre por el mismo motivo: la fecha no es lo que quieres predecir, así que es fácil no mirarla. Estás concentrado en predecir ventas, o bajas, o fallos, y la columna de fecha te parece un dato de fondo, casi decorativo. Es justo esa condición de dato secundario lo que la vuelve peligrosa: no la tienes presente al decidir cómo partir, barajas por costumbre, y la trampa queda montada. Acostúmbrate a buscar la fecha a propósito al principio de cada proyecto, aunque no vayas a predecirla, precisamente porque su papel en la validación es enorme aunque su papel en la predicción sea pequeño.

## Cómo se hace en código

En código, el corte temporal es más simple que el reparto al azar, no más complicado. Ni siquiera necesitas una función especial para barajar, porque precisamente no quieres barajar. Ordenas los datos por fecha si no lo están ya, eliges una proporción para el entrenamiento (por ejemplo, el 80% más antiguo), y cortas por ahí: la parte de abajo del calendario entrena, la de arriba examina. Es un corte por posición en el tiempo, no un sorteo.

Un aviso que ahorra sustos: al hacer un corte temporal, el examen cae todo en un periodo concreto, el más reciente, y eso tiene una consecuencia que hay que tener en cuenta. Si en ese último periodo pasó algo raro (una campaña, un pico de demanda, un cambio de tendencia), tu examen lo recogerá entero, y el número reflejará lo bien que el modelo maneja justo ese periodo. Eso no es un defecto del método, es la realidad: en producción también te tocará predecir periodos que a veces traen sorpresas. Pero conviene saberlo al leer el resultado, porque un examen que cae sobre un mes atípico puede dar un número peor del que el modelo tendría en un mes normal, y al revés. La solución, cuando importa, es examinar sobre varios periodos distintos (eso es justo lo que hace la validación cruzada temporal), para que el número no dependa de qué tramo final te tocó.

1# df esta ordenado por fecha, de lo mas antiguo a lo mas reciente
2corte = int(len(df) * 0.8)
3
4# El 80% mas antiguo entrena; el 20% mas reciente examina
5df_tr = df.iloc[:corte]
6df_te = df.iloc[corte:]
7
8print("Entreno hasta:", df_tr["fecha"].max())
9print("Examino desde:", df_te["fecha"].min())

El corte temporal es un corte por posición en el calendario, sin barajar.

La misma idea se aplica cuando quieres validación cruzada con datos que tienen fecha: no puedes rotar pliegues al azar, porque volverías a mezclar futuro y pasado. Existe una versión temporal de la validación cruzada que respeta el orden (entrena siempre con lo anterior a cada pliegue de examen), y es la que se usa en estos casos. Lo importante que te llevas hoy es el principio, no la variante concreta: con fechas de por medio, cualquier reparto que no respete el orden del tiempo está haciendo trampa.

Esa versión temporal funciona de forma intuitiva una vez tienes la imagen: en vez de que el examen rote por todas partes, va avanzando siempre hacia delante en el tiempo. En la primera ronda entrenas con los primeros meses y examinas con el mes siguiente; en la segunda, entrenas con esos meses más uno y examinas con el posterior; y así, ampliando el pasado conocido y empujando el examen siempre hacia el futuro. Nunca el examen cae antes que una parte del entrenamiento. Es como ir rehaciendo, mes a mes, la situación real en la que habrías estado: con lo que sabías hasta entonces, predecir lo que venía. Promedias esas rondas igual que en la validación cruzada normal, pero sin romper jamás la flecha del tiempo.

Conviene insistir en por qué este error es, de toda la familia de la validación, el que más cuesta en dinero. Los otros fallos que has visto suelen dejar alguna pista: un acierto perfecto que da mala espina, una brecha enorme que salta a la vista. El reparto al azar sobre datos con fecha no deja ninguna. El código corre, no hay excepción, el número sale alto y creíble, y nada en tu pantalla indica que has entrenado con el futuro. El modelo pasa todas las revisiones, se despliega con confianza, y solo entonces, prediciendo fechas de verdad nuevas, se revela que acierta mucho menos de lo prometido. Para cuando lo descubres, ya se han tomado decisiones con él. Es caro no porque sea más grave que los demás, sino porque es más silencioso, y lo silencioso llega más lejos antes de que alguien lo pare.

El reparto al azar sobre datos con fecha es la trampa más silenciosa de todas las que has visto, porque todo funciona: el código corre, no hay error, y el acierto es altísimo. Nada te avisa de que has entrenado con el futuro. El único que puede cazarlo eres tú, haciéndote la pregunta antes de partir: ¿tienen fecha mis datos y predigo hacia delante? Si nadie se la hace, el modelo llega a producción con una medida espectacular y fracasa el primer día, prediciendo fechas de verdad nuevas.

Este error (dejar que el entrenamiento vea información que en realidad pertenece al futuro, o al examen) es un caso particular de algo más general y más escurridizo todavía: dejar que la respuesta, o datos del examen, se cuelen en el entrenamiento sin que te des cuenta. El corte temporal mal hecho es una de las formas que toma ese problema. Pero hay otras, con disfraces distintos, y todas comparten el mismo síntoma mortal: un acierto irreal que se desmorona en producción. Es el error más caro del oficio, y es lo que cierra esta primera parte.

Regístrate para guardar tu progreso.