EfficientNet Food Classifier

A fine-tuned EfficientNet-B0 model for classifying food images into 8 categories. Trained using a two-stage transfer learning approach with ImageNet pre-trained weights.

Model Description

  • Architecture: EfficientNet-B0 + custom classification head
  • Task: Image Classification (8 food categories)
  • Framework: TensorFlow / Keras
  • Input: 224ร—224 RGB images
  • Pre-training: ImageNet

Classes

ID Label
0 Baked Potato
1 Burger
2 Crispy Chicken
3 Donut
4 Fries
5 Hot Dog
6 Pizza
7 Sandwich

Training

Two-Stage Transfer Learning

  1. Stage 1 โ€” Feature extraction: Backbone frozen, only classification head trained (LR: 1e-3)
  2. Stage 2 โ€” Fine-tuning: Backbone unfrozen (BatchNorm frozen), full model trained (LR: 2e-5)

Training Configuration

Parameter Value
Base Model EfficientNet-B0 (ImageNet)
Image Size 224 ร— 224
Batch Size 8
Stage 1 Epochs 12 (EarlyStopping patience=3)
Stage 2 Epochs 6
Optimizer Adam
Loss Sparse Categorical Crossentropy
Dropout 0.2
Data Augmentation RandomFlip, RandomRotation(0.05), RandomZoom(0.1), RandomContrast(0.1)

Dataset

Split Images
Train 3,797
Validation 813
Test 814
Total 5,424
  • Stratified 70/15/15 split with leak-free guarantee (SHA256 dedup)
  • Images sourced via DuckDuckGo image search, manually cleaned

Evaluation

Overall Metrics (Test Set)

Metric Score
Accuracy 0.9328
Precision (weighted) 0.9345
Recall (weighted) 0.9328
F1 (weighted) 0.9331
F1 (macro) 0.9301

Per-Class Performance

Class Precision Recall F1-score Support
Baked Potato 0.907 0.898 0.903 98
Burger 0.934 0.904 0.919 94
Crispy Chicken 0.860 0.968 0.911 95
Donut 0.986 0.958 0.971 142
Fries 0.926 0.917 0.921 96
Hot Dog 0.957 0.957 0.957 94
Pizza 0.971 0.918 0.944 73
Sandwich 0.906 0.923 0.914 52

Available Formats

Format File Size Use Case
Keras BestModelEfficientNetLite.keras 16 MB Python / TensorFlow
TFLite tflite/model.tflite 4.4 MB Mobile / Edge (dynamic range quantized)
TFLite float16 tflite/model_float16.tflite 7.8 MB Mobile / Edge (float16 quantized)
TFJS tfjs/model.json 15 MB Browser / Node.js

Usage

Python (Keras)

import tensorflow as tf
import numpy as np
from PIL import Image

# Load model
model = tf.keras.models.load_model(
    "BestModelEfficientNetLite.keras",
    custom_objects={"preprocess_input": tf.keras.applications.efficientnet.preprocess_input},
)

# Predict
img = Image.open("food.jpg").resize((224, 224))
x = np.expand_dims(np.array(img), axis=0).astype("float32")
probs = model.predict(x)[0]

classes = ["Baked Potato", "Burger", "Crispy Chicken", "Donut", "Fries", "Hot Dog", "Pizza", "Sandwich"]
print(f"Predicted: {classes[np.argmax(probs)]} ({probs.max():.1%})")

TFLite (Python)

import numpy as np
from PIL import Image
import tflite_runtime.interpreter as tflite

interpreter = tflite.Interpreter(model_path="tflite/model.tflite")
interpreter.allocate_tensors()

img = np.array(Image.open("food.jpg").resize((224, 224)), dtype=np.float32)
img = np.expand_dims(img, axis=0)

interpreter.set_tensor(interpreter.get_input_details()[0]['index'], img)
interpreter.invoke()
output = interpreter.get_tensor(interpreter.get_output_details()[0]['index'])

TFJS (JavaScript)

import * as tf from '@tensorflow/tfjs';

const model = await tf.loadGraphModel('tfjs/model.json');
const img = tf.browser.fromPixels(imageElement).resizeBilinear([224, 224]).expandDims(0).toFloat();
const predictions = model.predict(img);
const classIndex = predictions.argMax(-1).dataSync()[0];

Limitations

  • Trained on web-scraped images; may not generalize well to all food photography styles
  • Limited to 8 food categories
  • Best performance on clearly visible, single-item food images

License

Apache 2.0

Downloads last month
132
Inference Providers NEW
This model isn't deployed by any Inference Provider. ๐Ÿ™‹ Ask for provider support

Evaluation results