Dralkh commited on
Commit
c255bc1
·
verified ·
1 Parent(s): b2c09c7

Upload README.md with huggingface_hub

Browse files
Files changed (1) hide show
  1. README.md +29 -1
README.md CHANGED
@@ -52,6 +52,7 @@ Each model answered the same calorie question on the same dishes
52
  | Qwen3.5-9B (Q8_0, thinking off) ‡ | 304 | 117.2 | 64.5 | 65.8% | +6.1 |
53
  | MiniCPM-V 4.6 (1.3B) | 304 | 163.3 | 97.0 | 52.6% | +75.5 |
54
  | Gemma-4-12B † | 100 | 176.8 | 90.5 | 58.0% | −43.3 |
 
55
  | CalorieCLIP | 304 | 196.2 | 133.2 | 42.1% | +121.1 |
56
 
57
  † Gemma-4-12B was scored on a seeded 100-dish paired subset of the same 304 dishes (compute budget);
@@ -59,6 +60,33 @@ all parse rates were 100%.
59
  ‡ Qwen3.5-9B ran as an 8-bit GGUF (Q8_0) via llama.cpp with 4k context and thinking disabled.
60
  Notably it matches the 2B (117.2 vs 116.4 MAE) — 4.5× more parameters bought no accuracy on this task,
61
  suggesting the zero-shot VLM error floor is portion-mass ambiguity, not model capacity.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
62
 
63
  ## Training method
64
 
@@ -107,7 +135,7 @@ MODEL_ID = "google/siglip2-base-patch16-224"
107
  processor = AutoImageProcessor.from_pretrained(MODEL_ID)
108
  vision = SiglipVisionModel.from_pretrained(MODEL_ID)
109
  head = NutritionHead()
110
- state = torch.load(hf_hub_download("Dralkh/CalorieK", "kcalorie.pt"), map_location="cpu", weights_only=False)
111
  vision.load_state_dict(state["vision_state"]); head.load_state_dict(state["head_state"])
112
  vision.eval(); head.eval()
113
 
 
52
  | Qwen3.5-9B (Q8_0, thinking off) ‡ | 304 | 117.2 | 64.5 | 65.8% | +6.1 |
53
  | MiniCPM-V 4.6 (1.3B) | 304 | 163.3 | 97.0 | 52.6% | +75.5 |
54
  | Gemma-4-12B † | 100 | 176.8 | 90.5 | 58.0% | −43.3 |
55
+ | MiniMax M3 (hosted, thinking) | 304 | 193.5 | 120.5 | 44.7% | +103.7 |
56
  | CalorieCLIP | 304 | 196.2 | 133.2 | 42.1% | +121.1 |
57
 
58
  † Gemma-4-12B was scored on a seeded 100-dish paired subset of the same 304 dishes (compute budget);
 
60
  ‡ Qwen3.5-9B ran as an 8-bit GGUF (Q8_0) via llama.cpp with 4k context and thinking disabled.
61
  Notably it matches the 2B (117.2 vs 116.4 MAE) — 4.5× more parameters bought no accuracy on this task,
62
  suggesting the zero-shot VLM error floor is portion-mass ambiguity, not model capacity.
63
+ MiniMax M3 (a hosted reasoning model, chain-of-thought enabled) reinforces the point from the other
64
+ direction: extensive per-dish reasoning did not help — it lands second-to-last with a strong +104 kcal
65
+ systematic overestimate. Reasoning does not fix calibration.
66
+
67
+ ## Out-of-distribution evaluation (MM-Food-100K, 500 wild food photos)
68
+
69
+ To measure generalization beyond Nutrition5k plating, both regression models were scored on a seeded
70
+ 500-image sample of [MM-Food-100K](https://huggingface.co/datasets/Humanbased-AI/MM-Food-100K)
71
+ (restaurant/home photos; `food_prob ≥ 0.9`). **Caveat: these labels are crowd/AI estimates, not weighed
72
+ measurements** — absolute errors include label noise no model can beat, so the relative comparison is
73
+ the meaningful signal.
74
+
75
+ | | CalorieK | CalorieCLIP | |
76
+ |---|---|---|---|
77
+ | MAE | **164.9 kcal** | 206.4 kcal | 1.25× better |
78
+ | Median error | **139.1 kcal** | 179.9 kcal | 1.3× better |
79
+ | Within ±100 kcal | **36.0%** | 25.6% | |
80
+ | Bias | **−4.8 kcal** | +98.3 kcal | |
81
+ | R² | **+0.24** | −0.08 | |
82
+
83
+ Findings, stated honestly:
84
+ - CalorieK beats CalorieCLIP out-of-distribution on every metric, keeps **near-zero bias** on food it
85
+ has never seen, and retains real signal (R² +0.24) where CalorieCLIP is worse than predicting the
86
+ mean (R² −0.08).
87
+ - But CalorieK degrades ~3× versus in-distribution (51.4 → 164.9 kcal MAE): it is substantially a
88
+ specialist in Nutrition5k-style plated dishes. For wild-photo deployment, mixing diverse weakly
89
+ labeled data into training is the indicated next step.
90
 
91
  ## Training method
92
 
 
135
  processor = AutoImageProcessor.from_pretrained(MODEL_ID)
136
  vision = SiglipVisionModel.from_pretrained(MODEL_ID)
137
  head = NutritionHead()
138
+ state = torch.load(hf_hub_download("Dralkh/CalorieK", "caloriek.pt"), map_location="cpu", weights_only=False)
139
  vision.load_state_dict(state["vision_state"]); head.load_state_dict(state["head_state"])
140
  vision.eval(); head.eval()
141