Coffee Bag Premium Price Classifier (AutoGluon)
Homework 2, Problem 1.
What it does
Given seven things printed on a coffee bag (origin, altitude, whether altitude is printed, processing method, roast level, net weight in grams, whole or ground), the model predicts whether that coffee is premium (price per ounce above $1.08, the dataset median) or standard. It is a class exercise in AutoML, not a pricing tool.
Data
- Source: ssg1/coffee-bags-tabular, revision
84552e466c27. A classmate collected 34 real bags in September 2026. - Splits used exactly as published: train = 23 original bags + 322 jittered copies (345 rows), validation = 5 original bags, test = 6 original bags. Copies were made only from training bags, and I checked that no bag crosses splits.
- Target:
is_premium(1 = premium, 0 = standard). - Inputs:
origin,altitude_masl,altitude_stated,processing,roast_level,weight_g,grind. - Left out on purpose:
brand(identifies the product),price_usd(price divided by weight gives back the exact quantity the label is defined on),price_per_oz(the target itself), plus IDs and augmentation flags. - Preprocessing: none by hand. AutoGluon handles categorical encoding and missing values internally.
Training and search
- AutoGluon Tabular 1.6.1 in two stages. Stage A: random hyperparameter search, 20 trials per family, 600 s budget (took 87 s) over LightGBM, CatBoost, XGBoost, Random Forest, Extra Trees, k-NN and logistic regression. Search ranges are listed in the notebook.
- Stage B: the pretrained tabular foundation models Mitra, TabPFN v2 and TabICL at their defaults.
- Validation picked the classical stage.
- Selection metric: validation balanced accuracy. Bagging and stacking off, so jittered copies of one bag never get split up.
- Selected model:
WeightedEnsemble_L2, a weighted ensemble of: ExtraTrees/T1(weight 1.00):{"n_estimators": 100, "max_leaf_nodes": 15000, "n_jobs": -1, "bootstrap": true, "max_depth": null, "min_samples_leaf": 1, "random_state": 0}- Seeds: 24679 for data folds; AutoGluon's searcher and models use their default seed 0.
- Compute: Linux-6.6.122+-x86_64-with-glibc2.39, 2 CPU cores, no GPU used.
Results
Test set (6 original bags, never used for any choice):
| Metric | This model | Altitude rule baseline |
|---|---|---|
| Accuracy | 0.833 (5/6) | 0.833 |
| Balanced accuracy | 0.833 | 0.833 |
| F1 (premium) | 0.857 | 0.857 |
95% Wilson interval on test accuracy: [0.44, 0.97].
Because 6 bags is too few to trust, I also ran 5-fold cross-validation over all 34 original bags, retraining the winning configuration (ExtraTrees/T1 with its tuned settings) each fold:
- This model: 0.848 +/- 0.156 accuracy
- Altitude rule (predict premium if altitude is printed): 0.876 +/- 0.170 accuracy
Most important inputs by permutation importance on the 11 held-out bags: altitude_stated (0.17), roast_level (0.05), grind (0.03).
Limitations
- Tiny data: 34 real bags. One bag moves test accuracy by about 17 points. Treat every number here as rough.
- The jittered copies add density, not new coffees, so training scores are optimistic.
- "Premium" is relative to this sample's median, from one US region in September 2026. Prices change.
altitude_statedis a marketing choice that happens to track price. A model that leans on it is learning roaster behavior, not coffee quality.- Nothing here says anything about how good a coffee tastes.
Ethics
The data describes retail products, not people. No personal information is involved.
How to use
import zipfile, pandas as pd
from huggingface_hub import hf_hub_download
from autogluon.tabular import TabularPredictor
path = hf_hub_download("jackstev/hw2-coffee-premium-automl", "autogluon_predictor_dir.zip")
zipfile.ZipFile(path).extractall("coffee_model")
predictor = TabularPredictor.load("coffee_model")
bag = pd.DataFrame([{"origin": "Colombia", "altitude_masl": 1800, "altitude_stated": 1,
"processing": "washed", "roast_level": "light", "weight_g": 340, "grind": "whole"}])
print(predictor.predict(bag)) # 1 = premium, 0 = standard
Install autogluon.tabular[lightgbm,catboost,xgboost]==1.6.1 first. The pickle file needs matching library versions; the zip is the safer option.
License
MIT, matching the dataset.
AI usage disclosure
I used Claude (Anthropic) to help write this notebook and draft this model card. I chose the dataset, ran the notebook, and checked the results and the card against the outputs.