P4 Food-101 VGG-Style CNN with Batch Normalization and Label Smoothing

This repository contains a TensorFlow/Keras image classification model trained on the Food-101 dataset.
The model was designed as a lightweight CNN inspired by the VGG design principle of repeatedly stacking small 3×3 convolution layers before spatial downsampling.

The final model combines:

  • VGG-style repeated 3×3 convolution blocks
  • Batch Normalization after each convolution layer
  • ReLU activations
  • GlobalAveragePooling2D
  • Label Smoothing during training

The goal is to classify food images into 101 Food-101 classes.


Model Summary

Item Description
Task Image Classification
Dataset Food-101
Number of classes 101
Input size 128 × 128 × 3
Framework TensorFlow / Keras
Model file model.keras
Main architecture VGG-style lightweight CNN
Regularization Batch Normalization, Label Smoothing
Output layer Dense + Softmax

The model includes a Rescaling(1./255) layer internally, so input images should be provided as RGB arrays in the original 0–255 pixel range.


Architecture

The model is not the original VGG-16 architecture.
Instead, it uses the VGG idea of applying multiple 3×3 convolution layers before pooling, but with a smaller custom CNN structure.

A simplified block structure is:

Input image: 128 × 128 × 3
→ Rescaling(1./255)

→ Conv2D → BatchNorm → ReLU
→ Conv2D → BatchNorm → ReLU
→ MaxPooling2D

→ Conv2D → BatchNorm → ReLU
→ Conv2D → BatchNorm → ReLU
→ MaxPooling2D

→ Conv2D → BatchNorm → ReLU
→ Conv2D → BatchNorm → ReLU
→ MaxPooling2D

→ Conv2D → BatchNorm → ReLU
→ GlobalAveragePooling2D
→ Dense
→ Softmax output over 101 classes

Dataset Split

The model was trained using the Food-101 dataset with the following split:

Split Number of images
Train 60,600
Validation 15,150
Test 25,250

The official Food-101 test split was used only for final evaluation.
A validation set was separated from the official training split for model selection and early stopping.


Preprocessing

The preprocessing pipeline used during training was:

  1. Read image file path and label
  2. Decode JPEG image as RGB
  3. Resize image to 128 × 128
  4. Convert image to float32
  5. Convert label to one-hot encoding
  6. Batch and prefetch data

The model itself includes:

Rescaling(1./255)

Therefore, no external normalization is required at inference time if the input image uses the original 0–255 pixel range.


Training Configuration

Item Value
Optimizer Adam
Learning rate 0.001
Loss CategoricalCrossentropy(label_smoothing=0.1)
Batch size 64
Maximum epochs 80
EarlyStopping monitor val_accuracy
EarlyStopping patience 10
ModelCheckpoint monitor val_accuracy

EarlyStopping restored the best weights based on validation accuracy.
The best validation performance was reached before the maximum epoch limit.


Test Results

Final evaluation was performed on the Food-101 test set.

Metric Value
Test Loss 2.2240
Test Accuracy 0.5704
Test Top-5 Accuracy 0.8228

The Top-5 Accuracy indicates that the correct class was included among the model's top five predicted classes for approximately 82.28% of test images.


Repository Files

File Description
model.keras Trained Keras model
class_names.json Food-101 class labels
training_config.json Training, preprocessing, and evaluation configuration
inference.py Simple local inference helper
model_summary.txt Keras model architecture summary
test_result.csv Final test evaluation result
requirements.txt Minimal Python package requirements

Usage

Option 1. Load the model directly from Hugging Face

import os
os.environ["KERAS_BACKEND"] = "tensorflow"

import keras

model = keras.saving.load_model(
    "hf://neck392/p4-food101-vggstyle-cnn-bn-labelsmoothing"
)

Option 2. Use the included inference helper

Clone or download this repository, then run:

from inference import predict

result = predict("sample_food_image.jpg", top_k=5)
print(result)

Example output format:

[
    {"label": "pizza", "score": 0.42},
    {"label": "lasagna", "score": 0.18},
    {"label": "garlic_bread", "score": 0.09},
    {"label": "ravioli", "score": 0.07},
    {"label": "spaghetti_bolognese", "score": 0.05}
]

Local Inference Example

import json
import numpy as np
from PIL import Image
from tensorflow import keras

IMG_SIZE = 128

model = keras.models.load_model("model.keras", compile=False)

with open("class_names.json", "r", encoding="utf-8") as f:
    class_names = json.load(f)

image = Image.open("sample_food_image.jpg").convert("RGB")
image = image.resize((IMG_SIZE, IMG_SIZE))

arr = np.asarray(image).astype("float32")
arr = np.expand_dims(arr, axis=0)

# The model already includes Rescaling(1./255).
probs = model.predict(arr, verbose=0)[0]

top_k = 5
top_idx = np.argsort(-probs)[:top_k]

for idx in top_idx:
    print(class_names[int(idx)], float(probs[int(idx)]))

Intended Use

This model is intended for educational and experimental food image classification tasks using the Food-101 label space.

It may be useful for:

  • Food-101 classification experiments
  • CNN architecture comparison
  • Lightweight computer vision model demonstrations
  • Top-1 and Top-5 classification analysis

Limitations

  • The model was trained from scratch and does not use a large pretrained backbone.
  • Input images are resized to 128 × 128, which may lose fine-grained food texture details.
  • Visually similar food classes can still be confused, such as soups, desserts, sandwiches, or meat dishes.
  • The model is intended for Food-101 style images and may not generalize well to out-of-distribution images.
  • This model should not be used for medical, dietary, or nutrition-critical decisions.

Notes

This model uses the name "VGG-style" because it follows the VGG idea of stacking small 3×3 convolution layers before pooling.
It is not the original VGG-16 model and does not use pretrained VGG weights.


Citation

If you use this model or reproduce the project, please cite the Food-101 dataset and the relevant architecture papers:

L. Bossard, M. Guillaumin, and L. Van Gool,
"Food-101 – Mining Discriminative Components with Random Forests,"
Computer Vision – ECCV 2014 Workshops, 2014.

K. Simonyan and A. Zisserman,
"Very Deep Convolutional Networks for Large-Scale Image Recognition,"
International Conference on Learning Representations, 2015.

S. Ioffe and C. Szegedy,
"Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift,"
International Conference on Machine Learning, 2015.

M. Lin, Q. Chen, and S. Yan,
"Network in Network,"
International Conference on Learning Representations, 2014.

C. Szegedy, V. Vanhoucke, S. Ioffe, J. Shlens, and Z. Wojna,
"Rethinking the Inception Architecture for Computer Vision,"
IEEE Conference on Computer Vision and Pattern Recognition, 2016.
Downloads last month
4
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support