A food image classification project using transfer learning with ResNet18 and semi-supervised learning, classifying images into 11 food categories.
- Source: Food-11 (Kaggle)
- Size: ~16,000 images
- Classes: Bread, Dairy, Dessert, Egg, Fried Food, Meat, Noodles/Pasta, Rice, Seafood, Soup, Vegetable/Fruit
- Splits: Labeled training / Unlabeled training / Validation / Test
⚠️ Download the dataset from Kaggle and extract it into thefood-11/directory at the project root. See DATA.md for detailed setup instructions and class definitions.
food-11/
├── training/
│ ├── labeled/ # Labeled training data, organized into folders 00-10
│ └── unlabeled/ # Unlabeled data for semi-supervised learning
├── validation/ # Validation set
└── testing/ # Test set
food_classification/
├── model_utils/ # Model-related code
│ ├── data.py # Dataset classes, data loading & augmentation
│ ├── model.py # Model definitions & pretrained model loading
│ └── train.py # Training/validation loop with semi-supervised support
├── notebooks/ # Jupyter Notebooks
│ ├── 01_food_classification.ipynb
│ └── acc.png # Training accuracy curve
├── figures/ # Generated visualizations
│ ├── acc.png # Training accuracy curve
│ └── prediction_samples.png
├── model_save/ # Saved model weights (not version-controlled)
├── food-11/ # Full dataset (download separately)
├── food-11_sample/ # Small sample dataset (for testing)
├── main.py # Main training script
├── requirements.txt
├── DATA.md # Dataset documentation
├── LICENSE
└── README.md
pip install -r requirements.txtDownload the Food-11 dataset from Kaggle and extract it to the project root:
# Expected structure: food-11/training/labeled/00/, 01/, ..., 10/Option 1: Command line
python main.pyOption 2: Jupyter Notebook (recommended)
jupyter notebook notebooks/01_food_classification.ipynbThe notebook covers the full pipeline: data loading → model initialization → training → prediction visualization → accuracy curves.
Switch between pretrained models with a single line:
model, size = initialize_model("resnet18", num_classes=11, use_pretrained=True)
# model, size = initialize_model("vgg", num_classes=11, use_pretrained=True)
# model, size = initialize_model("densenet", num_classes=11, use_pretrained=True)
# model, size = initialize_model("MyModel", num_classes=11) # Custom CNNSupported architectures: ResNet18/50, VGG11, DenseNet121, GoogLeNet, AlexNet, SqueezeNet, Inception v3, and a custom CNN.
| Config | Value |
|---|---|
| Transfer Strategy | Fine-tuning (all parameters) |
| Data Augmentation | RandomResizedCrop + RandomHorizontalFlip + AutoAugment |
| Optimizer | AdamW (lr=5e-4, weight_decay=1e-4) |
| Loss Function | CrossEntropyLoss |
| Batch Size | 32 |
| Epochs | 50 |
Once validation accuracy exceeds 70%, semi-supervised learning is automatically enabled: the current model predicts labels for the unlabeled data, and samples with confidence > 99% are added to the training set as pseudo-labeled data.
| Metric | Value |
|---|---|
| Best Validation Accuracy | ~85% |
The best-performing model on the validation set is automatically saved to model_save/model.pth during training.
model_utils/data.py— CustomfoodDatasetclass for loading labeled/unlabeled data with augmentation;noLabDatasetclass for generating pseudo-labeled datasets.model_utils/model.py— Wraps multiple pretrained models with classifier head replacement; supports both linear probing and fine-tuning.model_utils/train.py— Training loop with integrated semi-supervised learning and automatic loss/accuracy curve plotting.main.py— Configures hyperparameters and launches training.
- If GPU memory is insufficient, reduce
batchSize(e.g., to 16) or use the smallerfood-11_sample/dataset for testing - Semi-supervised learning thresholds can be adjusted in
main.py(acc_thresandconf_thres)