EfficientNet Painting Style Detection Guide

Introduction

I fine-tuned EfficientNet-B0 to classify artworks into 9 painting styles using the Hugging Face dataset keremberke/painting-style-classification. The goal was to build a complete custom PyTorch pipeline covering dataset preparation, augmentation, transfer learning, and evaluation so I could better understand what helps and what limits accuracy on this task.

Model card: milliyin/painting-style-classification

Dataset Preparation

The dataset was downloaded directly from Hugging Face in ZIP format for train, validation, and test splits. The structure looked like this:

dataset/
  images/train
  images/validation
  images/test
  jsonl/train.jsonl
  jsonl/validation.jsonl
  jsonl/test.jsonl

Images were extracted, renamed with zero-padded IDs, and assigned numeric labels based on their folder names. I generated .jsonl metadata for each split and used a custom FolderDataset loader to read those files. A second wrapper, PaintingDataset, applied image transforms and returned (image, label) pairs for PyTorch.

Data Augmentation

For training:

For validation and test, I kept only resizing and normalization.

Model Architecture

I started from torchvision.models.efficientnet_b0 with ImageNet pretrained weights and replaced the final classifier with:

Transfer Learning Strategy

To reduce catastrophic forgetting and let the new classifier head adapt first, I froze layers up to roughly layer 100 at the start. Then I gradually unfroze the network:

This staged unfreezing gave the backbone time to adapt instead of changing everything at once.

Training Setup

criterion = nn.CrossEntropyLoss(label_smoothing=0.1)
optimizer = torch.optim.AdamW(model.parameters(), lr=1e-4, weight_decay=0.01)
scheduler = ReduceLROnPlateau(optimizer, mode="max", factor=0.5, patience=5)

The training loop tracked train loss, train accuracy, validation loss, and validation accuracy. Whenever validation accuracy improved, I saved the model checkpoint as best_efficientnet_b0.pth.

Evaluation & Results

Best validation accuracy achieved:

60.15% after 50 epochs

I also generated a classification report and plotted training curves to inspect overfitting behavior. Inference on individual images used the top prediction plus a confidence score.

Why Did It Plateau Around ~60%?

  1. High Inter-Class Similarity: Some styles, such as Romanticism and Realism, overlap visually.
  2. Label Noise: Open datasets can contain inconsistent labels.
  3. Data Imbalance: Some classes had fewer samples and learned less evenly.
  4. Limited Early Unfreezing: Freezing too much for too long slowed domain adaptation.
  5. Moderate Augmentation: Stronger augmentation could help with scan and framing variation.
  6. Model Size: EfficientNet-B0 is compact for a subtle classification problem like painting style detection.

How to Improve

Complete training pipeline, dataset processing, and fine-tuning notebook:

painting-style-classification-finetune/finetune.ipynb

Conclusion

This project gave me a practical look at fine-grained image classification for paintings. A baseline around 60 percent was useful, but the real value came from seeing exactly where augmentation, backbone size, and layer-unfreezing strategy can move the model further.