per-category-modeling-backfire
Skill5 starsChanged 35 days agoMITView on GitHub
Per-category/per-family models can produce WORSE leaderboard scores than a single global model, even when per-category CV is better. Use when: (1) Considering training separate models per product category/family/store in tabular competitions, (2) Per-category CV improves but LB degrades, (3) Each category has <100K rows from a larger dataset. Covers data volume thresholds, hybrid fallback strategies, and when per-category modeling is appropriate vs counterproductive.
In this repository63 other files it gives its agents.
- AGENTS.mdAGENTS.md
- adversarial-validation-kaggleSkill
- agent-nurture-frameworkSkill
- agent-session-memory-protocolSkill
- arxiv-paper-searchSkill
- autogluon-firstSkill
- autogluon-preset-strategySkill
- autogluon-timeseries-strategySkill
- catboost-first-tabularSkill
- claudeceptionSkill
- code-competition-artifact-pipelineSkill
- competition-orchestration-multimodelSkill
- context-engineeringSkill
- controlled-submission-experimentSkill
- cross-competition-feature-transferSkill
- cv-lb-gap-acknowledgmentSkill
- domain-knowledge-constraints-trapSkill
- ensemble-model-correlation-trapSkill
- feature-engineering-saturation-detectionSkill
- gpu-readiness-assessmentSkill
- gsd-loop-engineeringSkill
- kaggle-cognitive-cost-optimizationSkill
- kaggle-competition-best-practicesSkill
- kaggle-competition-type-strategySkill
- kaggle-data-format-firstSkill
- kaggle-discussion-searchSkill
- kaggle-experiment-sopSkill
- kaggle-oof-lb-validation-protocolSkill
- kaggle-optimal-blendingSkill
- kaggle-submission-format-by-metricSkill
- kaggle-top-performer-replicationSkill
- knowledge-crystallization-feedback-loopSkill
- ladder-drift-and-meta-aware-regressionSkill
- learned-value-beats-heuristic-augmentationSkill
- llm-competition-pipelineSkill
- mcts-pipeline-searchSkill
- mem0-dynamic-graph-memorySkill
- memory-hierarchy-managementSkill
- ml-sweet-spot-principleSkill
- model-ensemble-negative-weight-effectSkill
- multi-agent-rolesSkill
- multi-level-aggregation-overfittingSkill
- okf-visualize-knowledgeSkill
- onnx-minimal-network-designSkill
- progressive-verification-debuggingSkill
- ptcg-2ply-bounded-searchSkill
- ptcg-bc-large-model-submissionSkill
- retail-eda-frameworkSkill
- rmsle-zero-threshold-asymmetrySkill
- runtime-reflexionSkill
- sc-tir-mathematical-reasoningSkill
- self-evolving-skillsSkill
- skill-governance-and-automationSkill
- spatiotemporal-graph-feature-engineeringSkill
- store-sales-darts-chronos-blendSkill
- tabular-polynomial-features-breakthroughSkill
- three-layer-wisdom-extractionSkill
- time-series-walk-forward-validationSkill
- trueskill-simulation-competition-strategySkill
- ts-day-specific-forecastingSkill
- The first 60 shown.
The file
We split this skill into the rules it gives an agent
4 rules. About 0 are common, 4 are distinctive, and 0 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈4
Distinctive · estimate
This author's own choices. Worth a look.
0
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 32
Test predictions from per-category models have shifted mean (higher or lower than expected)
- Distinctive: line 70
No principled way to calibrate between the two prediction sources
- Distinctive: line 83
Before committing to per-category modeling:
- Distinctive: line 148
If each category has <100K rows, the global model's data advantage outweighs the specialization benefit.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Per-Category Modeling Backfire: When Splitting Data Hurts
Problem
A common "advanced" technique in Kaggle competitions is to train separate models for each category (e.g., per product family, per store, per region). While this seems intuitively correct—different categories have different patterns—it can backfire spectacularly when individual categories lack sufficient data volume.
Context / Trigger Conditions
Use when considering:
- Training separate GBDT models per product family, store, or region
- Per-category CV improves but leaderboard score degrades
- Each category has <100K rows but the full dataset has >1M rows
- Categories have highly imbalanced data volumes (some huge, some tiny)
- The global model already handles category differences via categorical features
Specific symptoms:
- Per-category CV: 0.367 (better) vs Global CV: 0.375 → Per-category LB: 2.10 vs Global LB: 1.86
- Small categories show high CV variance (>0.05 std across folds)
- Test predictions from per-category models have shifted mean (higher or lower than expected)
Solution
The Data Volume Threshold
Per-category modeling only works when each category has enough data to train a robust model.
| Rows per category | Per-category modeling | Recommendation |
| <50K | Harmful — overfitting, high variance | Use global model |
| 50K-200K | Risky — depends on problem complexity | Test both, compare LB |
| 200K-1M | Usually beneficial | Per-category if CV confirms |
| >1M | Almost always beneficial | Per-category recommended |
Why It Fails With Small Categories
- Overfitting: 70K rows × 5-fold CV = 14K validation rows. Easy to overfit.
- High variance: Small categories (BOOKS, HARDWARE) have CV std >0.05, meaning the model is unstable across folds.
- Feature instability: Lag/rolling features with limited history don't generalize.
- Loss of cross-category signal: Global model learns that "weekend → more sales" applies across ALL categories, amplifying this signal. Per-category models each must re-learn this from limited data.
Hybrid Approach Also Fails
A natural fallback—"use per-category for large categories, global for small"—also didn't work in practice:
Global model: LB = 1.86
Per-family (33 models): LB = 2.10 (worse)
Hybrid (15 per-family + global): LB = 2.13 (even worse!)The hybrid fails because:
- Predictions from per-family and global models have different scales/biases
- No principled way to calibrate between the two prediction sources
- The boundary (large vs small threshold) introduces discontinuities
When Per-Category DOES Work
Per-category modeling is appropriate when:
- Categories have genuinely different data-generating processes
- Each category has >200K rows
- The global model cannot capture category-specific patterns (no categorical features)
- Categories have different feature importance rankings
Verification
Before committing to per-category modeling:
# 1. Check data volume per category
for cat in categories:
n = len(train[train['category'] == cat])
if n < 100000:
print(f"WARNING: {cat} has only {n} rows - per-category model may overfit")
# 2. Check CV stability per category
for cat in categories:
cv_scores = cross_validate(cat_data)
if np.std(cv_scores) > 0.03:
print(f"WARNING: {cat} has unstable CV (std={np.std(cv_scores):.4f})")
# 3. Compare global vs per-category on HOLDOUT (not OOF)
global_pred = global_model.predict(test)
per_cat_pred = per_category_models.predict(test)
# If mean(per_cat_pred) differs significantly from mean(global_pred), per-category is suspectExample
Kaggle Store Sales Time Series Forecasting — 54 stores × 33 families:
Dataset: 2.35M clean rows, 1782 store-family combinations
Per-family: 33 families × ~71K rows each
Results:
├─ Global LightGBM: CV=0.375, LB=1.859 ✅ Best
├─ Per-family (33): CV=0.367, LB=2.102 ❌ 13% worse
└─ Hybrid (15+global): CV=—, LB=2.129 ❌ 15% worse
Analysis:
- Top 5 families (GROCERY I, BEVERAGES, PRODUCE, CLEANING, DAIRY):
CV 0.108-0.245, each >100K rows worth of sales → per-family helps
- Bottom 5 families (LINGERIE, CELEBRATION, GROCERY II, HARDWARE, AUTOMOTIVE):
CV 0.450-0.605, each with tiny sales → per-family hurts badly
- The bad families dragged the overall LB down more than the good families helped
Root cause: 71K rows per family is below the threshold for robust GBDT training.
The global model's 2.35M rows provide much more stable estimates.Notes
Related to Other Skills
- ml-sweet-spot: "More is not always better" — per-category is "more models" but not always better
- small-dataset-optimization-limits: Per-category creates small datasets from a large one
- ensemble-model-correlation-trap: Hybrid approach combines correlated predictions poorly
- ts-lag-nan-cascade-bug: The ffill fix that made the global model work well
Why TOP Solutions Use Per-Family
Many top Kaggle solutions DO use per-family models successfully. The difference:
- They use linear models (Ridge/Lasso) for small families, not GBDT
- They have more sophisticated features per family
- They use recursive prediction to handle lag features properly
- Their per-family models are often simpler (fewer trees, more regularization)
Key Insight
Per-category modeling is a sophistication that requires sufficient data per category. If each category has <100K rows, the global model's data advantage outweighs the specialization benefit.
References
- Kaggle Store Sales Competition: Global model LB=1.86, Per-family LB=2.10
- Web search confirms per-family is common winning strategy but typically with larger per-category datasets or simpler models (linear regression)
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

