zeyuai's picture
Upload README.md with huggingface_hub
5396d39 verified
---
license: apache-2.0
language: en
library_name: keras
tags:
- image-classification
- food-classification
- efficientnet
- tensorflow
- tflite
- tfjs
- transfer-learning
datasets:
- custom
pipeline_tag: image-classification
model-index:
- name: efficientnet-food-classifier
results:
- task:
type: image-classification
metrics:
- name: Accuracy
type: accuracy
value: 0.9328
- name: F1 (weighted)
type: f1
value: 0.9331
- name: Precision (weighted)
type: precision
value: 0.9345
- name: Recall (weighted)
type: recall
value: 0.9328
---
# 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)
```python
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)
```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)
```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