snack-category-automl-tabular

Predicts a packaged snack's category from its nutrition panel. Trained with AutoGluon TabularPredictor over a portfolio of boosted trees, tree ensembles, neural networks, linear models, nearest neighbours and tabular foundation models, bagged on parent_id-grouped, class-stratified folds.

Built for Homework 2 of 24-679 Designing with AI.

1. Purpose

Given the eight numbers on a nutrition label, predict which of five snack categories the product belongs to: candy, chips, cookies, crackers, granola_bars.

Intended use: coursework and demonstration of an AutoML workflow on a small tabular dataset. Out of scope: any dietary, nutritional, regulatory or purchasing decision.

2. Data origin and splits

Source: shanexf/packaged-snack-nutrition-data, collected by a classmate for HW1. I am not the dataset author and did not contribute to its collection.

Split Rows Used for
train 420 AutoGluon fit (bagged cross-validation)
validation + test 9 Held out; inspected once, after the fit returned

The training split contains roughly 20 rows per real snack, because the dataset author augmented each original product with numeric-jitter variants. Every fold is grouped by parent_id, supplied to AutoGluon through its groups argument, so all variants of one snack stay on the same side of every split. An ungrouped K-fold on this data returns an inflated, meaningless score.

Folds are also stratified by class. With roughly four real snacks per category, grouping alone produces folds whose training half is missing a category outright, which breaks the fit. The fold count was searched downward from 5 to the largest value where every training half retains all five classes; it came out at 4.

3. Features and target

Features (8, all numeric): serving_size_g, servings_per_container, calories, total_fat_g, sodium_mg, carbs_g, sugar_g, protein_g

Target: category — 5 classes.

Excluded: source_id, parent_id (row identity — leaks the label), and augmentation, is_augmented, second_parent_id, mix_weight (describe how a row was synthesised, not the snack).

4. Preprocessing

Handled by AutoGluon's own feature pipeline: type inference, imputation and per-model scaling are applied where the model family needs them. No manual feature engineering was performed. The source data has no missing values in the feature columns.

5. Training setup and search space

Library AutoGluon TabularPredictor 1.6.3
Objective eval_metric='f1_macro'
Validation 4-fold LeaveOneGroupOut on a StratifiedGroupKFold fold_id grouped by parent_id
Budget time_limit=900 s, 641.7 s actual, 16 models trained
HPO 8 random configurations per tunable family
Stacking num_stack_levels=0 — ~21 independent snacks cannot support a second level
Hardware Google Colab CPU runtime, no accelerator
Seed 20260922

Portfolio searched: LightGBM, CatBoost, XGBoost, random forest, extra trees, PyTorch NN, FastAI NN, linear model, k-NN, TabICL, TabPFNMix, and a DUMMY baseline. Families whose package is unavailable on the runtime are skipped and logged.

Selected model: WeightedEnsemble_L2 (best single model: NeuralNetFastAI_BAG_L1/5a625_00000)

Selected hyperparameters for NeuralNetFastAI_BAG_L1/5a625_00000:

{
  "layers": null,
  "emb_drop": 0.1,
  "ps": 0.1,
  "bs": 256,
  "lr": 0.01,
  "epochs": 30,
  "early.stopping.min_delta": 0.0001,
  "early.stopping.patience": 20,
  "smoothing": 0.0,
  "random_seed": 0
}

Ensemble composition:

Component Weight
TabPFNMix_BAG_L1 0.5714
NeuralNetFastAI_BAG_L1/5a625_00000 0.2857
LightGBM_BAG_L1/T1 0.1429

6. Metrics

Metric Value
Grouped out-of-fold macro-F1 (primary) 0.6462 ± 0.0591
Holdout accuracy (n=9) 0.889 (95 % CI ≈ ±0.205)
Holdout macro-F1 (n=9) 0.893
DUMMY baseline, same folds and metric 0.0000
Lift over baseline +0.6462

The out-of-fold figure is the one to quote, and the ± is the spread across folds — the variation you would see if the dataset's snacks had been a different set of snacks. The holdout has nine rows: its confidence interval is roughly ±30 percentage points, so it can only confirm the model is not broken.

7. Limitations

  1. The evidence base is ~21 real snacks. Row counts in the hundreds come from augmentation, not from independent observations. The grouped bagging accounts for this; the raw row count does not.
  2. The holdout is nine rows. Any comparison between this model and another on that holdout is noise.
  3. Nutrition panels underdetermine category. A granola bar and a cookie can have near-identical panels. There is an irreducible error floor here that no AutoML budget will pass.
  4. Single-annotator labels. Categories were assigned by one person, the dataset author, with no independent check.
  5. Narrow domain. Packaged Western supermarket snacks only. Nothing here transfers to fresh food, meals, or non-US labelling conventions.
  6. Augmentation is numeric jitter, so the model has seen a smooth neighbourhood around each real snack but no genuinely new products.
  7. Portfolio portability. If the foundation models or boosted-tree packages were unavailable on the runtime that produced this artifact, they were skipped; leaderboard.csv in this repo records exactly which models were actually trained.

8. Ethical considerations

The data describes commercial products, not people — no personal data is involved. The realistic harm is misuse as nutritional guidance: a category prediction is not a health claim, and a model trained on ~21 snacks should not inform anyone's diet. The limitations above are stated plainly rather than buried for that reason.

9. License

CC-BY-4.0, matching the source dataset's terms. Attribution to the dataset author for the underlying data.

10. Compute budget

Google Colab CPU runtime, no GPU. 16 models trained in 641.7 seconds under a 900-second limit.

11. AI usage disclosure

Generative AI (Claude, Anthropic) was used as a coding and writing assistant: it drafted the AutoGluon configuration, the fold-construction logic, the plotting code, and the prose of this card. The choices of task, target, feature exclusions, grouping strategy and evaluation design were reviewed and accepted by me, and every cell was executed and checked before upload. I am responsible for the content.

12. How to use

import pandas as pd
from huggingface_hub import snapshot_download
from autogluon.tabular import TabularPredictor

predictor = TabularPredictor.load(snapshot_download("sunkaiwen/snack-category-automl-tabular"), require_version_match=False)

x = pd.DataFrame([{
    "serving_size_g": 30.0, "servings_per_container": 8.0, "calories": 150.0,
    "total_fat_g": 8.0, "sodium_mg": 180.0, "carbs_g": 17.0,
    "sugar_g": 1.0, "protein_g": 2.0,
}])

print(predictor.predict(x))
Downloads last month
55
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support

Dataset used to train sunkaiwen/snack-category-automl-tabular