Malcolm Low | Practical AI, Computing & Quantum Research

Singapore-based practical guides, tutorials and experiments in AI, computing, modelling, simulation, optimisation and quantum computing, with research notes and hands-on workflows.

, , ,

Pocket Data Science VII: Store Sales Gradient Boosting on Android Termux

Ridge, CatBoost, and a hybrid residual ensemble for Kaggle Store Sales in Android Termux, reaching 0.41072 RMSLE and rank #116.

·

Written by

POCKET DATA SCIENCE • PART VII

A hands-on machine learning engineering study on Kaggle’s Store Sales benchmark: transitioning from deterministic heuristics to gradient-boosted decision trees, discovering why raw tree models struggle with retail scale disparities, engineering leakage-free multi-lag horizons, integrating Ecuador’s oil and holiday calendars, architecting a hybrid residual booster that smashes the Part VI baseline, and climbing 67 positions to Rank #116 globally (Top 21.0%) strictly on mobile edge hardware.

In Part VI of this series, we established that a disciplined ladder of non-machine learning heuristics could outperform 66.9% of Kaggle competitors, reaching 0.43150 RMSLE and securing Rank #183 out of 553 teams globally before training a single predictive model.

Yet heuristic baselines possess a structural ceiling: they cannot estimate promotional cross-price elasticities, capture non-linear oil price momentum, or dynamically model calendar interactions when municipal holidays coincide with semi-monthly paydays (quincenas). To push into the top tiers of the competition, we must transition to machine learning and gradient-boosted decision trees (GBDT).

💻 Open-Source Code: The entire experiment suite, CatBoost training pipelines, and submission scripts are maintained in our reproducible workspace on Android Termux with Google Antigravity CLI.
1  ·  The Machine Learning Edge Challenge

Running production-grade gradient boosting across 1,782 simultaneous time series spanning 3,000,000 transaction rows imposes strict constraints on mobile hardware:

  • Host Environment: Android running Termux with a Debian userspace via PRoot Distro on 64-bit ARM (aarch64).
  • AI Pair Programmer: Google Antigravity CLI (agy) executing in autonomous terminal sessions.
  • Hardware Budget: Strict 100% CPU execution, zero GPU acceleration, and a memory ceiling strictly capped below 500 MB RAM.

Over 5 live tournament submissions and a targeted regional calibration experiment, we advanced from an initial regularized linear model (0.49898) down to 0.41072, securing Rank #116 globally (Top 21.0%) and moving closer to the 0.400 threshold on Kaggle’s leaderboard.

2  ·  Target Mathematics & Leakage-Free Protocol

Metric Alignment Invariant

The competition evaluates Root Mean Squared Logarithmic Error (RMSLE):

RMSLE = sqrt( (1 / N) * sum( ( ln(1 + y_hat_i) - ln(1 + y_i) )^2 ) )

Because regression loss functions minimize Root Mean Squared Error (RMSE):

z = ln(1 + y)

Minimizing RMSE on z is mathematically identical to minimizing RMSLE on raw unit sales y. Predictions are inverted back to sales using exponential inversion with non-negative clipping: y_hat = max(0, exp(z_hat) - 1).

The 16-Day Validation Holdout Protocol

The test set spans 16 days (2017-08-16 to 2017-08-31). To prevent lookahead leakage, our validation set mirrors this exact 16-day duration: training on dates prior to 2017-08-01 (322,542 rows) and validating strictly on 2017-08-01 to 2017-08-15 (26,730 rows). Once hyperparameters and iteration stops are confirmed, models retrain on the complete dataset through 2017-08-15.

3  ·  The Machine Learning Scorecard & Tournament Ladder

Below is the complete progression of our machine learning architectures evaluated on Kaggle’s live public leaderboard and local holdout validation:

Experiment & Architecture Score / Metric Leaderboard & Validation Status
Part VI Heuristic Benchmark 0.43150 Rank #183 (Top 33.1%)
Exp 1: Regularized Linear Ridge 0.49898 Linear Anchor Floor
Exp 2: Native Categorical CatBoost 0.45786 -0.04112 vs. Exp 1
Exp 3: CatBoost + Exogenous Features 0.45390 -0.00396 vs. Exp 2
Exp 4: Hybrid Residual GBDT + Mask 0.42095 Rank #146 • Climbed 37 Places
Exp 5: Multi-Model Ensemble Blend 0.41072 Rank #116 • Climbed 67 Places
Exp 6: Sierra School Multiplier (2.6x) 0.41709 Regression: Asymmetric Overfit (See Part VIII)
Part VIII: Grandmaster Quad-Ensemble 0.40336 Rank #99 Globally • Global Top 100
Live Leaderboard Standing: Reached Rank #116 globally (Top 21.0%) out of 553 teams worldwide, climbing 67 places from our non-ML baseline.
4  ·  Experiment 1: Regularized Linear Ridge (0.49898)

Before deploying decision tree ensembles, we established a linear baseline using L2-regularized Ridge regression on log-sales:

from sklearn.linear_model import Ridge
import numpy as np
import pandas as pd

train = pd.read_csv("train.csv", parse_dates=["date"])
train_2017 = train[train["date"] >= "2017-01-01"].copy()
train_2017["target"] = np.log1p(train_2017["sales"])

# Construct features & fit Ridge
X = pd.get_dummies(train_2017[["onpromotion", "dayofweek", "is_weekend", "family"]], drop_first=True)
y = train_2017["target"]

model = Ridge(alpha=1.0)
model.fit(X, y)

The Result & Failure Mode: Ridge scored 0.49898. Linear models fail in multi-series grocery forecasting because they assume additive feature contributions. A promotion on high-velocity staples like GROCERY I creates a massive non-linear volume multiplier, whereas the same promotion on specialty goods produces negligible movement. Without explicit multiplicative terms, linear models cannot calibrate store-family promotional elasticity.

5  ·  Experiment 2: Native Categorical CatBoost GBDT (0.45786)

To model complex categorical interactions without one-hot dimensionality explosion, we deployed CatBoost (CatBoostRegressor). CatBoost uses symmetric oblivious trees and ordered target encoding, enabling fast inference on ARM mobile CPUs with zero thread lock.

The Leakage-Free Lag Horizon (Lags ≥ 16 Days)

In a 16-day recursive forecast horizon, utilizing 1-day lags (lag_1) causes autoregressive error compounding. To ensure direct single-pass forecasting without recursive drift, all lag features are strictly bounded by >= 16 days: lag_16, lag_21, and lag_28, with rolling statistics computed on lag_16.

from catboost import CatBoostRegressor

cat_features = ["store_nbr", "family", "city", "state", "type", "cluster"]
num_features = ["onpromotion", "is_weekend", "day", "dayofweek", "lag_16", "lag_21", "lag_28", "rolling_mean_7", "rolling_mean_14"]

cb = CatBoostRegressor(
    iterations=350,
    learning_rate=0.08,
    depth=6,
    loss_function="RMSE",
    cat_features=cat_features,
    random_seed=42,
    thread_count=4
)
cb.fit(X_tr, y_tr, eval_set=(X_val, y_val), early_stopping_rounds=40)

The Result: Slashed public RMSLE from 0.49898 to 0.45786 (-0.04112). However, pure CatBoost still trailed our Part VI domain heuristic (0.43150) because tree splits struggled to simultaneously calibrate extreme sales scale disparities across 1,782 series from lagged values alone.

6  ·  Experiment 3: CatBoost with Exogenous Data (0.45390)

Experiment 3 integrated macroeconomic indicators and holiday calendars into the feature matrix:

  • WTI Crude Oil Smoothing (oil.csv): Missing weekend prices were forward-filled; 7-day backward rolling mean and momentum differentials were computed.
  • Hierarchical Holiday Calendars (holidays_events.csv): Filtered exclusively for non-transferred active holidays, split into national, regional (state), and local (city) binary indicators.
  • Bi-Weekly Payday Flags (Quincenas): Marked the 15th and month-end dates along with distance-to-payday indicators.

The Result: Improved score to 0.45390 (-0.00396), resolving calendar-driven shopping dips.

7  ·  Experiment 4: Hybrid Residual Booster (0.42095 • Rank #146)

The critical architectural breakthrough came from recognizing that trees should not learn store-specific volume scale from scratch. We decomposed the target into a structured seasonal baseline plus residual:

z_i = ln(1 + Prior_i) + r_i

Where Prior_i is the 42-day grouped mean per (store_nbr, family, dayofweek) with the Sierra academic rush correction. CatBoost was trained strictly on the residual target r_i = ln(1 + y_i) - ln(1 + Prior_i).

Why Residual Boosting Smashed the Variance Floor

On raw log sales, initial tree training loss was 2.353. On residuals, initial loss plummeted to 0.698—a 70.3% variance reduction before the first split was made. The trees focused exclusively on promotion lifts and holiday shifts.

Promotion-Guarded Dead Catalog Post-Processing: Clamping predictions to 0.0 for series with 0 sales in the final 14 days and 0 promotions in test cleanly zeroed 2,278 inactive test rows.

The Result: Scored 0.42095 on the live leaderboard, beating our Part VI benchmark (0.43150) and jumping 37 places to Rank #146 globally.

8  ·  Experiment 5: Multi-Model Ensemble Blend (0.41072 • Rank #116)

In our top live tournament submission, we blended our two top model paradigms in log space:

ln(1 + y_ens) = 0.82 * ln(1 + y_hybrid) + 0.18 * ln(1 + y_exogenous)

Blending the variance-resistant hybrid residual booster (82%) with the dynamic exogenous tree model (18%) reduced individual model bias and pushed our score to 0.41072.

Tournament Placement: Reached Rank #116 out of 553 teams globally (Top 21.0%), climbing 67 positions from our non-ML baseline.

9  ·  Experiment 6: Sierra Academic Surge Calibration (Failed Blanket-Multiplier Test)

To push beyond 0.41072 into sub-0.400 territory, we diagnosed residual error distributions across all 33 product families. The largest remaining error spike was concentrated in SCHOOL AND OFFICE SUPPLIES during late August.

The Regional School Calendar Asymmetry

Ecuador operates on two distinct school calendars: the Costa (Coast) region starts classes in May, whereas the Sierra (Highlands / Andes) region (Quito, Ambato, Cuenca, Riobamba, Latacunga, Ibarra, Guaranda, Cayambe) starts classes on September 1st. In the final two weeks of August, school supply sales in Sierra stores experience a massive $2.6\times$ to $3.5\times$ surge that standard 42-day historical averages severely underestimate.

# Sierra cities academic multiplier for late August
sierra_cities = {"Quito", "Ambato", "Cuenca", "Riobamba", "Latacunga", "Ibarra", "Guaranda", "Cayambe"}
is_sierra_school = (df["city"].isin(sierra_cities)) & (df["family"] == "SCHOOL AND OFFICE SUPPLIES")

# Calibrated surge multiplier derived from historical holdouts
df.loc[is_sierra_school, "sales_pred"] *= 2.85

Local Holdout Validation: Testing this regional calibration on historical late-August holdouts dropped the RMSLE on Sierra school supplies by -0.18994 (from 0.63841 to 0.44847) and reduced overall dataset error by -0.00423, projecting live leaderboard performance to ~0.406.

Kaggle Submission Result & Continued in Part VIII: When submitted to Kaggle, this blanket 2.6x heuristic regressed to 0.41709 RMSLE due to asymmetric RMSLE over-prediction penalties across unpromoted Sierra stores. The post-mortem of this failure, compiling native LightGBM and XGBoost on ARM64 Termux, and breaking into the Global Top 100 at 0.40336 RMSLE (Rank #99) with our Quad-Ensemble is covered in Pocket Data Science VIII: Kaggle Store Sales Quad-Ensemble & Global Top 100 on Android Termux.
10  ·  Hardware Resource Audit & Edge Reproducibility

Below is the resource profile recorded inside Android Termux on 64-bit ARM:

Pipeline Stage Wall Clock Time Peak Resident RAM
Ridge Regression (Exp 1) 12.1 s 312 MB
Pure CatBoost GBDT (Exp 2) 391.3 s 468 MB
Exogenous CatBoost (Exp 3) 169.7 s 442 MB
Hybrid Residual GBDT (Exp 4) 23.3 s 415 MB
Ensemble Blend (Exp 5) 2.1 s 188 MB

Edge Takeaway: By decomposing scale disparities and using vectorized relational merges, entire multi-stage gradient boosting pipelines train and infer on multi-million row datasets comfortably within 500 MB of mobile RAM.

11  ·  Core Lessons for Production Time Series Engineering
  • Never Force Decision Trees to Learn Cross-Sectional Scales from Scratch: In multi-series retail forecasting, tree leaf quantization errors on extreme volume disparities cripple performance. Decomposing demand into a structured seasonal prior and modeling the log residual delivers massive gains in convergence speed and accuracy.
  • Direct Horizon Lags Prevent Compounding Autoregressive Drift: Restricting lag features strictly to ≥ 16 days eliminated the instability of multi-step recursive rollouts, producing deterministic single-pass predictions.
  • Guard Zero-Forecasts with Promotional Intent: Blindly setting inactive series to zero creates severe penalties when retailers re-launch seasonal items. Always gate zero-demand masks with promotional intent (onpromotion == 0).
  • Ensemble Distinct Modeling Paradigms: Combining an anchored residual model with a free-form tree booster captured structural day-of-week rhythms and non-linear promotion shocks simultaneously.
12  ·  Reproducing on Android via Termux

To execute all machine learning experiments inside Android Termux:

# Navigate to workspace
cd ~/kaggle_store_sales

# Run Experiment 1: Regularized Linear Ridge
python3 exp1_ridge.py

# Run Experiment 2: Native Categorical CatBoost
python3 exp2_catboost.py

# Run Experiment 3: CatBoost with Exogenous Data
python3 exp3_catboost_exogenous.py

# Run Experiment 4: Hybrid Residual GBDT
python3 exp4_hybrid_residual.py

# Run Experiment 5: Multi-Model Ensemble Blend
python3 exp5_ensemble_blend.py

# Run Experiment 6: Sierra Academic Surge Calibration test
python3 exp6_sub40_calibrated.py

# Submit to Kaggle
kaggle competitions submit -c store-sales-time-series-forecasting \
  -f submission_exp6_sub40_calibrated.csv \
  -m "Experiment 6: Sierra Academic Surge Multiplier Test"

Comments

One response to “Pocket Data Science VII: Store Sales Gradient Boosting on Android Termux”

  1. Pocket Data Science VIII: Kaggle Store Sales Quad-Ensemble – Malcolm Low | Practical AI, Computing & Quantum Research Avatar

    […] Part VII of this series, we transitioned from deterministic heuristics to gradient-boosted decision trees, constructing a […]

    Like

Leave a Reply