Classifying Food Images with Deep Learning and Transfer Learning

Food classification is an important computer vision task with many real-world applications, from nutrition tracking to food service automation. The goal is to accurately categorize images of food items into predefined classes like "pizza", "sushi", "apple", etc.

In recent years, deep learning has enabled remarkable progress in food image classification. Convolutional neural networks (CNNs) can learn rich, hierarchical visual features directly from food image data, without relying on hand-engineered features. With enough training data, deep CNNs can match or even exceed human-level performance on challenging food datasets like Food-101 and ETHZ Food-101.

However, training accurate CNN food classifiers from scratch requires very large datasets with tens or hundreds of thousands of labeled images. Collecting such massive datasets is time-consuming and expensive. Training state-of-the-art CNN architectures like ResNet-101 or Inception-v4 on huge datasets also demands significant computational resources—often multiple high-end GPUs.

Fortunately, transfer learning provides an effective solution to these challenges. The key idea is to leverage CNNs that have already been pre-trained on large-scale image datasets like ImageNet, which contains 1.2 million images across 1000 object categories. Although ImageNet doesn‘t contain food categories, the low- and mid-level visual features learned by CNNs trained on ImageNet tend to generalize well to other computer vision tasks, including food classification.

By fine-tuning a pre-trained ImageNet model on a smaller dataset of food images, we can train highly accurate food classifiers with orders of magnitude less data and computation compared to training from scratch. Fine-tuning involves:

  1. Removing the original fully-connected classification layer
  2. Adding a new fully-connected layer with the desired number of food classes
  3. Freezing the weights of some or all of the pre-trained convolutional layers
  4. Training the new fully-connected layer and optionally the last few convolutional layers on the food dataset

Popular CNN architectures for transfer learning include:

  • VGG16 / VGG19: Relatively simple architecture with 16 or 19 layers and small 3×3 convolutional filters. Computationally efficient and easy to fine-tune.

  • Inception-V3: Sophisticated architecture with multiple parallel convolutional branches, including 1×1 convolutions. Highly accurate but relatively slow.

  • ResNet-50: Deep residual learning framework with 50 layers. Skip connections enable stable training. Balances accuracy and efficiency.

  • MobileNet: Streamlined architecture optimized for mobile and embedded vision applications. Useful for deploying food classification models on smartphones and edge devices.

In this tutorial, we‘ll walk through the process of fine-tuning a pre-trained ResNet-50 model for binary food/non-food classification using TensorFlow and Keras. We‘ll be using the Food-5K dataset, which contains 5000 images evenly split between food and non-food classes.

Step 1: Imports and Setup

First, let‘s import the necessary libraries and configure the dataset paths.

import tensorflow as tf
from tensorflow import keras
import numpy as np
import matplotlib.pyplot as plt

IMG_SIZE = (224, 224)
BATCH_SIZE = 32
NUM_CLASSES = 2
EPOCHS = 20

train_dir = ‘Food-5K/training‘
val_dir = ‘Food-5K/validation‘
test_dir = ‘Food-5K/evaluation‘

Step 2: Create Data Generators

Next, we‘ll set up data generators to load images from disk and dynamically augment them to improve model robustness. We‘ll resize all images to 224×224 to match the input size of ResNet-50.

train_datagen = keras.preprocessing.image.ImageDataGenerator(
rescale=1./255,
rotation_range=25,
zoom_range=0.2,
width_shift_range=0.2,
height_shift_range=0.2,
shear_range=0.2,
horizontal_flip=True,
fill_mode=‘nearest‘)

val_datagen = keras.preprocessing.image.ImageDataGenerator(rescale=1./255)

train_generator = train_datagen.flow_from_directory(
train_dir,
target_size=IMG_SIZE,
batch_size=BATCH_SIZE,
class_mode=‘binary‘)

val_generator = val_datagen.flow_from_directory(
val_dir,
target_size=IMG_SIZE,
batch_size=BATCH_SIZE,
class_mode=‘binary‘)

Step 3: Load Pre-trained Base Model

Now we‘ll load the pre-trained ResNet-50 model and freeze the convolutional base. We‘ll also add a new fully-connected classification layer for our binary food/non-food classes.

base_model = keras.applications.ResNet50(
weights=‘imagenet‘,
include_top=False,
input_shape=(224, 224, 3))

base_model.trainable = False

inputs = keras.Input(shape=(224, 224, 3))
x = base_model(inputs, training=False)
x = keras.layers.GlobalAveragePooling2D()(x)
outputs = keras.layers.Dense(1, activation=‘sigmoid‘)(x)
model = keras.Model(inputs, outputs)

model.compile(optimizer=keras.optimizers.Adam(),
loss=keras.losses.BinaryCrossentropy(),
metrics=[keras.metrics.BinaryAccuracy()])

model.summary()

Step 4: Train the Model

With our model compiled, we can launch training. We‘ll train for 20 epochs using binary cross-entropy loss. The pre-trained weights will stay frozen.

history = model.fit(
train_generator,
epochs=20,
validation_data=val_generator)

Step 5: Fine-tune the Model

If we want to squeeze out additional performance, we can unfreeze the last convolutional block of the ResNet base and jointly fine-tune those layers with the new classification layers. This allows the model to adapt the higher-level features to our specific food dataset.

base_model.trainable = True

for layer in base_model.layers[:-10]:
layer.trainable = False

model.compile(optimizer=keras.optimizers.RMSprop(learning_rate=0.00001),
loss=keras.losses.BinaryCrossentropy(),
metrics=[keras.metrics.BinaryAccuracy()])

fine_tune_epochs = 10
total_epochs = EPOCHS + fine_tune_epochs

history_fine = model.fit(
train_generator,
epochs=total_epochs,
initial_epoch=history.epoch[-1],
validation_data=val_generator)

Step 6: Evaluate Performance

Finally, we can evaluate the fine-tuned model on the test set and display some sample predictions.

test_loss, test_acc = model.evaluate(test_generator)
print(‘Test accuracy:‘, test_acc)

The fine-tuned ResNet-50 should achieve over 95% classification accuracy on the Food-5K test set. Not bad for a model trained in minutes rather than days!

To further optimize performance, we could explore techniques like:

  • Progressive resizing (gradually increase resolution during training)
  • Two-stage transfer learning (different learning rates for different layers)
  • Class-balanced sampling (ensure equal representation of food and non-food images per batch)
  • Test-time augmentation (average predictions across multiple augmented versions of each image)
  • Model ensembles (combine predictions from multiple different architectures)

Food image classification has numerous exciting applications. Smartphone apps can use food classifiers to automatically log meals and track nutrition just by snapping photos. Restaurants can optimize their processes by monitoring food preparation with computer vision. Grocery stores can automate the checkout process by visually identifying items. The possibilities are endless.

Looking ahead, an important challenge is generalizing food classification models to handle the full diversity and messiness of real-world eating. Most food datasets today are limited to a few hundred classes of pristine, centered food items against plain backgrounds. But real meals often involve many foods jumbled together on a cluttered plate or table. There is also huge regional and cultural diversity in foods, ingredients, and eating customs around the world.

To address these challenges, future research directions may include:

  • Multi-label classification (tagging images with all contained food items)
  • Weakly-supervised localization (finding the position of each food item)
  • Ingredient recognition (identifying component foods and estimating amounts)
  • Integrated food + human activity recognition (detecting eating actions and context)

With further progress, food classification technology can help tackle important societal challenges like nutrition monitoring, food safety, eating behavior change, and hunger relief. By making it easier to understand what people eat, we can empower individuals and institutions to make smarter choices about food.

I hope this tutorial has given you a taste of the potential of deep learning and transfer learning for food image classification. Feel free to experiment with different architectures, datasets, and hyperparameters to advance the state-of-the-art. Bon appétit!

How useful was this post?

Click on a star to rate it!

Average rating 0 / 5. Vote count: 0

No votes so far! Be the first to rate this post.

Similar Posts