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 VIII: Kaggle Store Sales Quad-Ensemble

Why a 2.6x back-to-school multiplier and a 52-week lag both hurt our RMSLE, why leaf-wise LightGBM beat CatBoost, and how a four-paradigm ensemble trained on a phone reached Kaggle’s Top 100.

ยท

Written by

POCKET DATA SCIENCE • PART VIII (STORE SALES ML • PART II)

How we climbed into Kaggle’s Store Sales Top 100 on mobile hardware: diagnosing why a back-to-school multiplier and a 52-week lag backfired, examining the structural limits of oblivious decision trees, running native LightGBM and XGBoost on Android Termux ARM64, and building a four-paradigm Quad-Ensemble that broke the 0.404 floor to reach Rank #99 globally at 0.40336 RMSLE.

In Part VII of this series, we transitioned from deterministic heuristics to gradient-boosted decision trees, constructing a hybrid residual CatBoost pipeline that reached 0.41072 RMSLE and climbed to Rank #116 globally. We stood on the threshold of the top tier, yet our attempts to push further with single-architecture models stalled.

Breaking into Kaggle’s Global Top 100 required diagnosing two consecutive submission regressions, understanding why CatBoost’s oblivious trees struggle with localized promotional effects, and building a multi-engine ensemble directly inside an Android Termux PRoot environment without a single server or cloud GPU.

๐Ÿ† Kaggle Milestone Reached: Rank #99 out of 565 teams globally (Global Top 100 / Top 17.5%) with 0.40336 RMSLE (Team: Malcolm / myhlow). All models trained in under 2.5 minutes on a phone CPU using under 500 MB RAM.
1  ·  The Tournament Ladder & Scorecard

The progression across our second wave of experiments is shown below. Scores marked LB are Kaggle public leaderboard results; scores marked Val are from our local 16-day holdout (2017-08-01 to 2017-08-15).

Experiment & Architecture RMSLE (Source) Status
Part VI Non-ML Baseline 0.43150 (LB) Rank #183 (Top 33.1%)
Exp 5: Hybrid CatBoost Blend (Part VII) 0.41072 (LB) Rank #116 (Baseline Anchor)
Exp 6: Sierra School Multiplier (2.6x) 0.41709 (LB) Regression: Uniform Scaling Overfit
Exp 7: 52-Week Lag + Horizon Split 0.41901 (LB) Regression: Noisy Annual Lag
Standalone Leaf-Wise LightGBM 0.40810 (Val) Beat Standalone CatBoost (0.41110 Val)
Exp 8: 75% Base + 25% LightGBM 0.40403 (LB) Rank #104 • Up 12 Places
Exp 8.1: 60% Base + 40% LightGBM 0.40408 (LB) Blend Weight Insensitivity Check
Exp 9: Quad-Ensemble 0.40336 (LB) Rank #99 Globally (Top 100) • Best Score
Exp 10: SLSQP Constrained Stacking 0.40426 (LB) Regression: Holdout-Fitted Weights (0.40182 Val)
Public Leaderboard Verified: We climbed from Rank #116 to Rank #99 globally, officially entering the Top 100.
2  ·  Anatomy of a Kaggle Regression: Experiments 6 and 7

Before achieving our breakthrough, we suffered two sharp regressions on the public leaderboard. Understanding why these intuitive ideas failed is more instructive than the eventual improvement itself.

The Blanket Multiplier Trap (Experiment 6: 0.41709)

In Ecuador, the Sierra region experiences a strong back-to-school surge in late August. On local validation holdout, multiplying SCHOOL AND OFFICE SUPPLIES sales by a calibrated factor of 2.6x in Sierra stores cut that family’s holdout error from 0.63841 to 0.44847.

Confident in this domain discovery, we submitted Experiment 6 to Kaggle. The result was a regression from 0.41072 to 0.41709. Why? The Root Mean Squared Logarithmic Error (RMSLE) measures error in log space, so it scores relative error rather than absolute error:

RMSLE = sqrt( 1/N * sum( (log(pred_i + 1) - log(actual_i + 1))^2 ) )

Predicting 50 units when actual demand is 10 costs log(51/11) = 1.534, while a 40-unit miss on a 1,000-unit series costs only log(1041/1001) = 0.039. Back-to-school purchasing across Ecuador’s 54 stores is highly heterogeneous, and several smaller Sierra stores sell only a handful of school supplies per day, or none at all. A uniform 2.6x multiplier is harmless on high-volume series, but on low-volume and near-zero series it turns small absolute errors into large ratio errors, and those rows dominate the score. Our holdout gain came from a few large stores; the test period punished the many small ones.

The Annual Lag Pollution (Experiment 7: 0.41901)

In Experiment 7, we attempted to capture year-over-year seasonality by introducing a 52-week (364-day) lag (lag_364) alongside a split of the 16-day forecast horizon. The model regressed further to 0.41901.

Because Experiment 7 changed two things at once, we cannot attribute the regression to the lag alone. Our working hypothesis is that lag_364 for the August 2017 test window points back to August 2016, when sales were still recovering from the disruption of the April 2016 Ecuador earthquake. With only four years of history, a single annual lag carries one noisy observation per date, which gradient boosting can easily overfit. Isolating the two changes is on our list for a future experiment.

Engineering Rule: Never apply blanket heuristic scaling factors across an entire retail cohort. Heterogeneous calendar surges are better learned by non-linear tree splits conditioned on store size and promotions.
3  ·  The Oblivious Tree Bottleneck in CatBoost

CatBoost had been our primary modeling engine throughout Parts II, V, and VII. While exceptional at preventing categorical target leakage, CatBoost builds symmetric (oblivious) decision trees:

  • Oblivious Tree Property: At depth d, every decision node across the entire tree is forced to split on the exact same feature and threshold.
  • The Retail Sparsity Problem: In retail forecasting, high promotional activity is rare and deeply localized. A large promotional surge (e.g. onpromotion > 25) only triggers demand spikes for specific product families (such as GROCERY I or BEVERAGES) in high-volume stores (Type A).

Because oblivious trees must apply the same split condition across every branch at a given level, isolating a sparse interaction among 1,782 series requires deeper trees (depth 8 to 10). On mobile CPUs, deeper trees sharply increase training time and tend to overfit non-promoted rows.

We realized we needed an asymmetric, best-first tree architecture: LightGBM.

4  ·  Running Native LightGBM & XGBoost on ARM64 PRoot

Conventional wisdom holds that running multi-library gradient boosting on mobile hardware is either unsupported or prohibitively slow. Inside our Android Termux Debian PRoot environment, we installed official pre-built Linux aarch64 wheels with no compilation required:

pip install lightgbm xgboost --break-system-packages

Both libraries ran without issues on the phone’s 8-core ARM Cortex processor. By keeping our dataset memory-optimized using int8, float32, and Pandas category dtypes, our total memory footprint remained under 500 MB RAM:

Modeling Engine CPU Wall Clock Time Memory Footprint
LightGBM Regressor (650 trees) 13.2s ~185 MB RAM
XGBoost Regressor (650 trees) 11.1s ~210 MB RAM
CatBoost Regressor (550 iterations) 108.3s ~380 MB RAM
Total Quad-Ensemble Pipeline 135.0s (2.25 min) < 500 MB RAM (peak)
5  ·  The Leaf-Wise Advantage: LightGBM Beats CatBoost

Unlike depth-wise or oblivious tree growth, LightGBM uses leaf-wise (best-first) tree splitting. It expands the leaf that produces the largest decrease in loss, allowing the tree to grow asymmetric branches that focus on complex promotional sub-populations:

# Leaf-wise LightGBM configuration
m_lgb = lgb.LGBMRegressor(
    n_estimators=650,
    learning_rate=0.06,
    num_leaves=63,
    subsample=0.8,
    colsample_bytree=0.8,
    min_child_samples=40,
    random_state=42,
    n_jobs=4,
    verbose=-1
)

Evaluating standalone LightGBM on our 16-day holdout (2017-08-01 to 2017-08-15) gave 0.40810 RMSLE, outperforming standalone CatBoost (0.41110) by 0.00300 in less than one-eighth of the training time.

6  ·  Experiment 8 & 8.1: The Blended Leap to 0.40403

Rather than replacing our existing models entirely, we recognized that our Part VII hybrid base (Experiment 5: domain prior plus CatBoost residual correction) provided a well-regularized anchor for weekly store-level velocity. We constructed a linear blend in logarithmic space:

# Experiment 8 Blend (75% Base + 25% Leaf-Wise LightGBM)
log_pred_exp8 = 0.75 * np.log1p(sales_exp5) + 0.25 * pred_lgb
sales_exp8 = np.clip(np.expm1(log_pred_exp8), 0, None)

We submitted Experiment 8 to Kaggle. The score dropped from 0.41072 to 0.40403, moving us 12 positions up to Rank #104 globally.

To test sensitivity to the blend weight, we submitted Experiment 8.1 with LightGBM at 40% (60% Base + 40% LightGBM). It scored 0.40408, showing that the blend had plateaued around 0.404 and that further gains would need a different kind of model rather than a different weight.

7  ·  Experiment 9: The Quad-Ensemble (Top 100)

Ensembles generalize best when their members make different kinds of errors. Our Quad-Ensemble combines four modeling paradigms in three blend components, since the Experiment 5 anchor already contains two of them:

  • Hybrid Anchor (70%): The Experiment 5 base, made of (1) a domain heuristic prior capturing day-of-week seasonality and paydays, corrected by (2) a symmetric-tree CatBoost residual model.
  • (3) Leaf-Wise LightGBM (20%): Captures localized promotional effects via best-first splits.
  • (4) Depth-Wise XGBoost (10%): Adds level-wise histogram trees with different regularization and split dynamics.
# Quad-Ensemble (domain prior + CatBoost inside log_exp5)
log_ensemble = 0.70 * log_exp5 + 0.20 * log_lgb + 0.10 * log_xgb
sales_ensemble = np.clip(np.expm1(log_ensemble), 0, None)

Upon submitting Experiment 9 to Kaggle, our score dropped to 0.40336 RMSLE, breaking the 0.404 plateau:

๐ŸŽ‰ Global Top 100 Milestone: Official Kaggle Leaderboard Rank #99 out of 565 teams (Malcolm / myhlow), up from Rank #116 at the start of this session.
8  ·  Experiment 10: When Optimized Blend Weights Overfit

With our daily Kaggle submission quota exhausted, we turned to local optimization to see whether data-driven blend weights could beat the hand-set 70/20/10 split of Experiment 9.

SLSQP Constrained Optimization

Using scipy.optimize.minimize with Sequential Least Squares Programming (SLSQP), we solved for blending weights bounded between [0, 1] subject to sum(w) == 1.0 on our holdout validation set:

Optimal Stacking Weights:
Domain Prior Base: 0.60
LightGBM Regressor: 0.25
XGBoost Regressor:  0.10
CatBoost Regressor: 0.05
Holdout Optimized RMSLE: 0.40182

The Leaderboard Verdict

On the holdout, the optimized blend looked like our best model yet. On the public leaderboard, Experiment 10 scored 0.40426: worse than the hand-set Quad-Ensemble (0.40336) and 0.00244 behind its own validation estimate.

The cause is selection bias. The weights were fitted on the same holdout window used to score them, so the optimizer tuned itself to the quirks of early August 2017 rather than to patterns that carry into the test window. The coarse 70/20/10 split absorbed less of that noise and generalized better.

Engineering Rule: Never score blend weights on the same data used to fit them. Fit weights on one validation window and confirm them on another (or across several time-series origins), and treat small optimizer gains on a single holdout with suspicion.

Dead-Series Guardrail with Promotional Gating

Experiment 10 also applied a guardrail that is independent of the blend weights. In retail data, certain product families are discontinued or inactive. If a store has zero sales for a product family over the preceding 14 days and has zero scheduled promotions (onpromotion == 0), tree models often predict a residual trickle of 0.1 to 0.4 units. Because RMSLE penalizes non-zero predictions on true zero rows, we identified 144 dead store-family pairs and enforced zero-sales masks across 2,278 test rows.

9  ·  Key Takeaways for Production Time Series Engineering

Our progression from a simple non-ML baseline to a Global Top 100 ensemble yielded five practical principles:

  • Ensemble Divergent Paradigms: Blending models from the same algorithmic family (e.g. multiple CatBoost seeds) yields marginal gains. Combining a domain statistical prior, symmetric CatBoost, leaf-wise LightGBM, and depth-wise XGBoost improved our leaderboard score from 0.41072 to 0.40336.
  • Tree Architecture Shapes What Is Learned: Symmetric oblivious trees excel at global categorical stability but struggle with sparse localized interactions. Leaf-wise splitting handles promotional retail spikes more naturally.
  • Know What Your Metric Rewards: RMSLE scores relative error, so mistakes on low-volume and near-zero series weigh as much as mistakes on the biggest sellers. Blanket manual multipliers should be replaced with learned, conditioned interactions.
  • Simple Blend Weights Generalize Better: SLSQP-optimized weights improved our holdout score to 0.40182 but scored 0.40426 on the leaderboard, losing to a hand-set 70/20/10 blend. Weights fitted on the scoring holdout are biased toward that window.
  • Edge Hardware is Sufficient: Competitive time series forecasting does not require server farms or GPUs. With disciplined memory management, a three-library GBDT ensemble trains in under 2.5 minutes on a mobile CPU.
10  ·  Reproducing on Android via Termux

The pipeline script below trains all three engines and writes the Experiment 10 stacked submission. To reproduce our best-scoring Experiment 9 result instead, apply the 70/20/10 blend from Section 7 to the same model outputs.

# Navigate to competition workspace
cd ~/kaggle_store_sales

# Install native ARM64 gradient boosting engines
pip install lightgbm xgboost catboost --break-system-packages

# Train all engines and write the Experiment 10 stacked submission
python3 exp10_grandmaster_sub40_ready.py

# Verify submission integrity
head -n 5 submission_exp10_grandmaster_sub40_ready.csv

The Pocket Data Science Roadmap

Explore the complete journey of competitive machine learning executed entirely on Android mobile edge hardware:

Comments

One response to “Pocket Data Science VIII: Kaggle Store Sales Quad-Ensemble”

  1. Kaggle Store Sales CatBoost on Android Termux Avatar

    […] 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 […]

    Like

Leave a Reply