Skip to content

Repository files navigation

☕ Starbucks Beverage Calorie Classifier (Decision Tree + Streamlit)

Classifies a Starbucks beverage as High Calorie (> 185 kcal, the dataset median) or Low Calorie using a scikit-learn Decision Tree, with a Streamlit app that loads the saved model.

Project structure

app.py              Streamlit app (loads model.joblib, never retrains)
predict.py          Load model, validate inputs, predict (shared helpers)
train_model.py      Preprocess, tune, evaluate, plot, save
model.joblib        Saved Pipeline (preprocessing + tree)
metrics.json        Metrics, config, feature ranges
graphs/             Generated PNGs (+ depth_sweep.csv)
data/starbucks.csv  Original dataset (unchanged)
notebooks/          Original EDA notebook (unchanged)
requirements.txt

Method

  • Target: Calories > 185 → High (121 High / 121 Low).
  • Leakage control: Calories and beverage name are excluded from features. The split is StratifiedGroupKFold grouped by beverage name, so sizes/milks of one drink never appear in both train and test (asserted in code).
  • Cleaning: headers stripped; % removed from vitamin columns; Varies (caffeine) and 3 2 (one fat value) become missing and are median-imputed inside the pipeline (fit on training data only); categoricals one-hot encoded.
  • Tuning: GridSearchCV (grouped stratified 5-fold, scored by log loss) over max_depth, min_samples_leaf, criterion, ccp_alpha. Seed 42.
  • Loss: binary log loss -mean(y·log p + (1-y)·log(1-p)). Accuracy is reported separately and is not a loss.

Results (measured by train_model.py)

Tuned params: max_depth=2, min_samples_leaf=10, criterion=gini, ccp_alpha=0.02. Train 191 rows / test 54 rows.

Accuracy Log loss Precision Recall F1
Train 0.915 0.196 0.868 0.979 0.920
Test 0.833 0.350 0.750 1.000 0.857

Test confusion matrix (rows = actual): Low → 18 correct, 9 wrongly High; High → 27/27 correct. Over 5 grouped folds, accuracy averaged 0.890 ± 0.030 (range 0.833–0.913).

Train > test is the normal generalisation gap. With only 54 test rows, one split is noisy, so prefer the 5-fold figure.

Honest caveats

  • Nutrients ≈ calories. Calories ≈ 4·carbs + 4·protein + 9·fat, so nutrient inputs carry much of the answer even without the Calories column. Don't read this as discovering hidden structure.
  • A secondary run without macronutrient features scored 0.926 test accuracy on the same split. On 54 rows that difference is within noise, so don't conclude macros hurt.
  • The depth-sweep graphs hold the other tuned parameters fixed (ccp_alpha=0.02), so curves flatten after depth 3. At depth 3 the test loss is lower than at the CV-chosen depth 2; I kept the CV choice rather than picking by test results.
  • Feature importance is dominated by cholesterol (~0.85), likely a proxy for dairy/cream content.
  • Small dataset (242 rows, 33 distinct drinks).

Run locally

python -m venv .venv && source .venv/bin/activate   # Windows: .venv\Scripts\activate
pip install -r requirements.txt
python train_model.py      # optional: regenerates model, metrics, graphs
python predict.py          # command-line prediction demo
streamlit run app.py

Deploy on Streamlit Community Cloud

  1. Create a GitHub repo and push this folder (keep model.joblib, metrics.json, graphs/, data/):
    git init && git add . && git commit -m "Starbucks decision tree app"
    git branch -M main
    git remote add origin https://github.com/<your-username>/<repo>.git
    git push -u origin main
  2. Go to https://share.streamlit.io/ and sign in with GitHub.
  3. Click Create app → choose the repo, branch main, main file path app.py.
  4. Click Deploy. Streamlit installs requirements.txt and gives you a public URL.

requirements.txt pins scikit-learn==1.8.0 because model.joblib was saved with it; if the Cloud environment cannot install that version, relax the pin and re-run python train_model.py locally to regenerate model.joblib, then push again.

Releases

Packages

Contributors

Languages