Time Series · Forecasting · Data Leakage · MLOps

🪤 Availability Leakage — the CV winner you shouldn't ship

🪤 Leakage de Disponibilidad — el ganador del CV que no deberías shipear

A CRISP-ML(Q) study on availability leakage using the Kaggle Store Sales dataset (Corporación Favorita, Ecuador). Headline finding: transactions correlates 0.84 with store sales and tops feature importance, but it doesn't exist at forecast time — so a model that uses it wins in cross-validation (RMSLE 0.1275) and then collapses in production (0.1872), losing to an honest model that never used it (0.1528). The leak doesn't inflate a score — it inverts model selection. And its severity is grain-dependent.

Un estudio CRISP-ML(Q) sobre leakage de disponibilidad con el dataset de ventas de Favorita (Kaggle, Ecuador). Hallazgo principal: transactions correlaciona 0.84 con las ventas y encabeza la importancia de features, pero no existe al momento de pronosticar — así que un modelo que la usa gana en validación cruzada (RMSLE 0.1275) y luego se desploma en producción (0.1872), perdiendo contra un modelo honesto que nunca la usó (0.1528). El leak no infla un score — invierte la selección de modelo. Y su severidad depende del grano.

📊 Dataset: Store Sales — Favorita (Kaggle, Corporación Favorita)
📝 Records: Registros: 3.0M filas · 1,782 series (54 stores × 33 families) · 2013–2017
🏭 Industry: Industria: Retail · Demand Forecasting · Supply Chain Retail · Demand Forecasting · Supply Chain
🎯 Metric: Métrica: RMSLE · honest temporal holdout (16 days)
Python pandas LightGBM XGBoost CatBoost statsforecast Data Leakage CRISP-ML(Q)
🎯
Business
📊
Data
🔧
Preparation
🧠
Modeling
Evaluation
🚀
Deployment
01

🎯 Business Understanding

Retailers forecast daily sales per store and product family to drive replenishment, staffing and promotions. The failure this lab targets isn't a weak model — it's a leaky feature that survives every sanity check except one: availability at inference time. The decision at stake is model selection. If a feature that won't exist in production makes the wrong model look best in validation, you deploy it and pay the gap on every restock decision.

This trap is named availability leakage: a contemporaneous covariate that is technically non-future (it's from "today") but is operationally unavailable at forecast time. It's the hardest class of leakage to catch because standard checks — correlation, AUC, time-based split — pass it silently. Only an inference-time availability audit exposes it.

Project goals:

  • Demonstrate the full lifecycle of an availability leak: detection → quantification → honest holdout → production simulation.
  • Show that trusting CV on a leaky model inverts model selection — you ship the worse model.
  • Establish that leak severity is grain-dependent: audit at the grain you actually forecast.
  • Provide a one-line audit protocol reusable on any production pipeline.

El retail pronostica ventas diarias por tienda y familia para reponer inventario, asignar personal y planificar promociones. La falla que ataca este lab no es un modelo débil — es una feature con leak que pasa todos los chequeos menos uno: disponibilidad en inferencia. La decisión en juego es la selección de modelo. Si una feature que no existirá en producción hace que el modelo equivocado parezca el mejor en validación, lo despliegas y pagas la brecha en cada decisión de reposición.

Esta trampa se llama leakage de disponibilidad: una covariable contemporánea que es técnicamente no-futura (es de "hoy") pero está operativamente indisponible en el momento del pronóstico. Es la clase de leakage más difícil de detectar porque los chequeos estándar — correlación, AUC, split temporal — la dejan pasar silenciosamente. Solo una auditoría de disponibilidad en inferencia la expone.

Objetivos del proyecto:

  • Demostrar el ciclo completo de un leak de disponibilidad: detección → cuantificación → holdout honesto → simulación de producción.
  • Mostrar que confiar en el CV con un modelo leaky invierte la selección de modelo — se shipea el peor.
  • Establecer que la severidad del leak depende del grano: auditarlo al grano en que realmente pronosticas.
  • Proveer un protocolo de auditoría de una línea reutilizable en cualquier pipeline de producción.
Problem type
Tipo de problema
Time-series regression (panel data) + leakage audit
Regresión de series de tiempo (panel) + auditoría de leakage
Target
sales (daily, per store × family)
sales (diaria, por tienda × familia)
Main metric
Métrica principal
RMSLE
Holdout
Holdout
Last 16 training days (mirrors Kaggle test window)
Últimos 16 días de entrenamiento (espeja la ventana de test de Kaggle)
Stakeholder
Demand Planner / ML Engineer reviewing a pipeline
Demand Planner / ML Engineer revisando un pipeline
02

📊 Data Understanding

1,782 series (54 stores × 33 families), train 2013-01-01 → 2017-08-15, test the next 16 days. Quality gates verify against the data, not assumptions: the series count, that test.csv carries no transactions, that transactions.csv stops at the last training day and never covers the test window, and the 0.84 correlation that motivates the thesis. We also resolve the 8 transferred national holidays so the calendar marks the day each was actually celebrated.

The most important pre-modeling finding: transactions (store-level daily ticket count) is a same-day signal with ρ = 0.84 with sales — and it is absent from both test.csv and the inference window. It tops feature importance in any model that sees it, and that's exactly the trap.

1,782 series (54 tiendas × 33 familias), train 2013-01-01 → 2017-08-15, test los 16 días siguientes. Los quality gates verifican contra los datos: el conteo de series, que test.csv no trae transactions, que transactions.csv termina el último día de train y nunca cubre el test, y la correlación 0.84 que motiva la tesis. También resolvemos los 8 feriados nacionales transferidos para que el calendario marque el día real de celebración.

El hallazgo más importante antes de modelar: transactions (conteo diario de tickets por tienda) es una señal del mismo día con ρ = 0.84 con las ventas — y está ausente tanto de test.csv como de la ventana de inferencia. Domina la importancia de features en cualquier modelo que la ve, y esa es exactamente la trampa.

Diagnostic Diagnóstico Result Resultado
transactionssales correlation ρ = 0.84 ⚠️ (strong same-day signal, absent at inference)(señal fuerte del mismo día, ausente en inferencia)
Feature importance rank of transactionsRank de importancia de transactions #1 at store×day grain · #4 at store×family#1 al grano tienda×día · #4 a tienda×familia
Series countConteo de series 1,782 (54 stores × 33 families)
Transferred holidays resolvedFeriados transferidos resueltos 8
Coverage of transactions.csvCobertura de transactions.csv Train only — stops at 2017-08-15, never covers the test windowSolo train — termina el 2017-08-15, nunca cubre el test

⚠️ Honest caveat: the result is the contrast, not the absolute RMSLE (which depends on sample, horizon and tuning). We studied one leak (transactions) on a sample of series; other contemporaneous signals deserve the same audit. At the store×family grain the leak is negligible — we report that plainly.

⚠️ Caveat honesto: el resultado es el contraste, no el RMSLE absoluto (que depende de muestra, horizonte y tuning). Estudiamos un leak (transactions) sobre una muestra de series; otras señales contemporáneas merecen la misma auditoría. Al grano tienda×familia el leak es negligible — lo reportamos sin adornos.

03

🔧 Data Preparation

Two grains: store×day (where transactions is a strong same-day signal) and the competition-native store×family. Features avoid leakage by construction — sales lags and rolling stats shifted ≥ horizon, calendar fields, transfer-resolved holiday flag, oil price (known for test), onpromotion (present in test). The whole contrast is one feature pair:

  • A = same-day transactions (leak) — the optimistic scenario a careless modeler creates.
  • B = transactions lagged by the horizon (honest) — the inference-safe alternative.

Dos granos: tienda×día (donde transactions es señal fuerte del mismo día) y el nativo de la competencia, tienda×familia. Las features evitan leakage por construcción — lags y rolling desplazados ≥ horizonte, calendario, flag de feriado transfer-resuelto, precio del petróleo (conocido para test), onpromotion (presente en test). Todo el contraste es un par de features:

  • A = transactions del mismo día (leak) — el escenario optimista que crea un modeler descuidado.
  • B = transactions rezagado por el horizonte (honesto) — la alternativa segura para inferencia.
# The entire leakage experiment is one feature swap.
# A: same-day transactions — valid in a CV that has the holdout's true transactions,
#    but INVALID in production (transactions.csv ends on the last training day).
features_A = base_features + ['transactions']          # leak

# B: lagged transactions — available at inference time, shifted >= horizon.
features_B = base_features + ['transactions_lag_16']   # honest

# Quality gate: assert transactions is absent from test.csv
assert 'transactions' not in test_df.columns, \
    "Unexpected: test.csv has transactions — check the dataset version"

The production simulation (A_prod) is the critical third scenario: model A trained with the leaky feature, but at holdout time transactions is hidden and imputed with its last known value — exactly what a production system would do. This is what the model actually delivers if deployed.

La simulación de producción (A_prod) es el tercer escenario crítico: el modelo A entrenado con la feature leaky, pero en el holdout transactions está oculta e imputada con su último valor conocido — exactamente lo que haría un sistema de producción. Eso es lo que realmente entrega el modelo si se deploya.

04

🧠 Modeling

One strong model (LightGBM) at store×day grain, evaluated three ways on the honest holdout. A tight model zoo frames the experiment: univariate forecasters (Naive, SeasonalNaive, ETS, Theta, AutoARIMA via statsforecast) are immune to the leak and set the trustworthy ceiling; only models that ingest exogenous features (LightGBM, XGBoost, CatBoost) can fall for it.

Un modelo fuerte (LightGBM) a grano tienda×día, evaluado de tres formas sobre el holdout honesto. Un model zoo tight enmarca el experimento: los univariados (Naive, SeasonalNaive, ETS, Theta, AutoARIMA vía statsforecast) son inmunes al leak y marcan el techo confiable; solo los modelos que ingieren exógenas (LightGBM, XGBoost, CatBoost) pueden caer en la trampa.

Model / Scenario Modelo / Escenario RMSLE Notes Notas
Naive (lag-16) 0.3083 Floor — leak-immune baselinePiso — baseline inmune al leak
AutoARIMA (statsforecast) 0.1827 Honest univariate — beats the leaky model in productionUnivariado honesto — le gana al leaky en producción
B — honest LightGBM (lagged transactions only)(solo transactions rezagado) 0.1528 The real winnerEl ganador real
A_cv — LightGBM with leak, CV scorecon leak, score de CV 0.1275 The "brag" — looks best in CVEl "presumido" — parece mejor en CV
A_prod — LightGBM with leak, production realitycon leak, realidad producción 0.1872 Collapses — transactions hidden as in productionSe desploma — transactions oculta como en producción
            Same dataset · Same 16-day holdout · Same LightGBM

  A_cv   (transactions present = how CV is typically reported)  RMSLE 0.1275 ← "looks best"
  B      (transactions lagged = honest)                         RMSLE 0.1528 ← real winner
  A_prod (transactions hidden = production reality)             RMSLE 0.1872 ← reality

  Trust CV → ship A → pay +0.0344 RMSLE vs B, forever.
  Brag→reality gap: +0.0597 (47% worse than reported CV)
05

✅ Evaluation

The double punch.

  • (1) CV inflation: gap = A_prod − A_cv = +0.0597 RMSLE — the leak inflates CV by 47%. If you only look at CV scores, model A looks 47% better than its production performance.
  • (2) Selection inversion: A beats B in CV (0.1275 < 0.1528) and loses in production (0.1872 > 0.1528). Trusting CV makes you ship the worse model. Even an honest AutoARIMA (0.1827) beats the leaky model in production.

Grain-dependent severity

transactions is a store-level ticket count. At the competition's native store×family grain it is a weak proxy for any single family, so the trap nearly disappears:

El doble golpe.

  • (1) Inflación del CV: gap = A_prod − A_cv = +0.0597 RMSLE — el leak infla el CV un 47%. Si solo miras los scores de CV, el modelo A parece 47% mejor de lo que rinde en producción.
  • (2) Inversión de selección: A le gana a B en CV (0.1275 < 0.1528) y le pierde en producción (0.1872 > 0.1528). Confiar en el CV te hace shipear el peor modelo. Hasta un AutoARIMA honesto (0.1827) le gana al modelo leaky en producción.

Severidad dependiente del grano

transactions es un conteo de tickets a nivel tienda. Al grano nativo de la competencia tienda×familia, es un proxy débil para cualquier familia individual, así que la trampa casi desaparece:

store×day store×family
Gap (brag → reality)Gap (brag → realidad) +0.0597 +0.0074
transactions importance rankrank de importancia #1 #4
Selection inversionInversión de selección ClearClara Within noiseDentro del ruido

Segment-dependent: worst where it looks best

The CV inflation is ~5× larger in high-traffic stores (gap +0.098) than in low-traffic ones (+0.020) — the leaky model looks best exactly where it will hurt most. This is the insidious part: the stores with the highest business impact are the ones where the CV is most misleading.

Lesson: audit availability at the grain you actually forecast, not by intuition.

Dependiente del segmento: peor donde se ve mejor

La inflación del CV es ~5× mayor en tiendas de alto tráfico (gap +0.098) que en las de bajo tráfico (+0.020) — el modelo leaky se ve mejor justo donde más va a doler. Esta es la parte insidiosa: las tiendas con mayor impacto de negocio son donde el CV es más engañoso.

Lección: audita la disponibilidad al grano en que vas a forecastear, no por intuición.

06

🚀 Deployment

There's no deployed model or demo here — and that's the point. For this lab the CRISP-ML "Deployment" phase is an audit protocol, not an app. The whole lesson is about not shipping the wrong model.

A short availability audit — for each feature, ask whether it exists at inference, re-score with it hidden, and check for selection inversions, at your forecast grain — turns an invisible, recurring loss into a one-line check.

The audit protocol:

Aquí no hay modelo desplegado ni demo — y ese es justamente el punto. Para este lab la fase "Deployment" de CRISP-ML es un protocolo de auditoría, no una app. Toda la lección es sobre no shipear el modelo equivocado.

Una auditoría corta de disponibilidad — por cada feature, preguntar si existe en inferencia, re-evaluar ocultándola, y buscar inversiones de selección, al grano en que pronosticas — convierte una pérdida invisible y recurrente en un chequeo de una línea.

El protocolo de auditoría:

def availability_audit(model, X_val, y_val, feature_name, imputation='last_known'):
    """
    For each candidate feature, simulate its absence at inference time.
    If score_hidden >> score_present: the feature is an availability leak.
    If model_A(hidden) > model_B(never_saw_it): selection inversion — ship B.
    """
    score_present = rmsle(model.predict(X_val), y_val)

    X_hidden = X_val.copy()
    X_hidden[feature_name] = impute(X_val[feature_name], method=imputation)
    score_hidden = rmsle(model.predict(X_hidden), y_val)

    gap = score_hidden - score_present
    print(f"{feature_name}: CV={score_present:.4f} | prod={score_hidden:.4f} | gap={gap:+.4f}")
    return gap

This lab has no Streamlit demo — the result is a methodology, not a deployed model. The notebooks (notebooks/Favorita_Sales_CRISPML.ipynb EN and notebooks/Favorita_Sales_CRISPML_ES.ipynb ES) are the primary artifact. They are generated from shared code cells so both languages stay synchronized.

Limitations, stated plainly:

  • Absolute RMSLE depends on sample, horizon and tuning — the contrast is the result, not the numbers.
  • We studied one leak (transactions) on a sample of series; other contemporaneous signals deserve the same audit.
  • At the store×family grain the leak is negligible — we report that plainly.

Este lab no tiene demo Streamlit — el resultado es una metodología, no un modelo desplegado. Los notebooks (notebooks/Favorita_Sales_CRISPML.ipynb EN y notebooks/Favorita_Sales_CRISPML_ES.ipynb ES) son el artefacto principal. Se generan desde celdas de código compartidas para que ambos idiomas estén sincronizados.

Limitaciones, sin adornos:

  • El RMSLE absoluto depende de muestra, horizonte y tuning — el contraste es el resultado, no los números.
  • Estudiamos un leak (transactions) sobre una muestra de series; otras señales contemporáneas merecen la misma auditoría.
  • Al grano tienda×familia el leak es negligible — lo reportamos sin adornos.
💡

Business Impact

Impacto de Negocio

Availability leakage costs aren't about a single bad prediction — they're about structural mis-selection: deploying the wrong model for every forecast cycle until the leak is discovered. In a pipeline forecasting daily replenishment across 54 stores and 33 families (1,782 series), a +0.0597 RMSLE gap on every prediction compounds into a chronic over- or under-stock bias.

El costo del leakage de disponibilidad no es una predicción mala — es una mala selección estructural: desplegar el modelo equivocado en cada ciclo de pronóstico hasta que se descubra el leak. En un pipeline que pronostica reabastecimiento diario en 54 tiendas y 33 familias (1,782 series), un gap de +0.0597 RMSLE en cada predicción se acumula en un sesgo crónico de sobre- o sub-stock.

The one-sentence business case: the availability audit takes one engineer one day to run; the alternative is paying a +0.0344 RMSLE forecast penalty on every restock decision until someone notices the model underperforms in production — which, in typical ML ops without active monitoring, can be months.

El negocio en una frase: la auditoría de disponibilidad le toma un día a un ingeniero; la alternativa es pagar un penalizador de +0.0344 RMSLE en cada decisión de reposición hasta que alguien note que el modelo rinde mal en producción — lo que, en ML ops típico sin monitoreo activo, puede tardar meses.

What this lab teaches that most don't

  • Availability leakage is the hardest class of leakage to catch. Standard checks — correlation, feature importance, time-based split — all pass it. Only the inference-time availability audit exposes it.
  • Leak severity is grain-dependent. A signal that's devastating at store×day (rank #1, clear inversion) is negligible at store×family (rank #4, gap within noise). Audit at the grain you actually forecast.
  • The leak inflates CV most where it will hurt most. High-traffic stores see ~5× more CV inflation — the model looks best exactly where operational impact is highest.
  • Univariate methods are leak-immune. Naive and AutoARIMA can't cheat with exogenous features. That's not a weakness — it's what makes them the trustworthy ceiling in this experiment.

Lo que este lab enseña y la mayoría no

  • El leakage de disponibilidad es la clase más difícil de detectar. Los chequeos estándar — correlación, feature importance, split temporal — lo dejan pasar. Solo la auditoría de disponibilidad en inferencia lo expone.
  • La severidad del leak depende del grano. Una señal devastadora a tienda×día (rank #1, inversión clara) es negligible a tienda×familia (rank #4, gap dentro del ruido). Audita al grano en que realmente pronosticas.
  • El leak infla más el CV donde más va a doler. Las tiendas de alto tráfico ven ~5× más inflación de CV — el modelo se ve mejor justo donde el impacto operativo es mayor.
  • Los métodos univariados son inmunes al leak. Naive y AutoARIMA no pueden hacer trampa con features exógenas. No es una debilidad — es lo que los hace el techo confiable en este experimento.
🔍

Sources

Fuentes

Quantitative claims and methodological decisions in this lab are supported by the dataset itself, verified quality gates, and the following references.

Las afirmaciones cuantitativas y decisiones metodológicas de este lab se apoyan en el propio dataset, quality gates verificados y las siguientes referencias.

Dataset

Dataset

Store Sales — Time Series Forecasting (Kaggle, Corporación Favorita, Ecuador). License: competition rules apply.

CRISP-ML(Q) methodology

Metodología CRISP-ML(Q)

Studer S. et al. (2020). Towards CRISP-ML(Q). arXiv:2003.05155 · MDPI MAKE 3(2)

Classical forecasting (statsforecast)

Forecasting clásico (statsforecast)

Nixtla statsforecast — Naive, SeasonalNaive, AutoETS, AutoTheta, AutoARIMA.

Data leakage

Data leakage

IBM Think — What is Data Leakage? · scikit-learn — Lagged Features for Time Series