Fine-tuning an ImageNet-pretrained ResNet-18 on the Oxford 102 Category Flower Dataset.
This project uses Python 3.10+. There are two ways to install the dependencies.
Option 1: uv (recommended)
If you have uv installed, it reads pyproject.toml
and creates the environment automatically:
uv sync
Then run any command in this README with uv run in front, e.g.
uv run python code/prepare_data.py.
Option 2: pip
pip install torch torchvision numpy matplotlib pillow scipy pandas
A GPU is recommended but not required. The code runs on CPU as well, just slower.
The dataset is not downloaded automatically, you must place it in the data/
folder yourself. Download the Oxford 102 Flowers dataset and arrange it like this:
data/
├── jpg/ # all 8189 flower images (image_00001.jpg ... image_08189.jpg)
├── setid.mat # the official train/val/test split
└── imagelabels.mat # the per-image class labels
jpg/, setid.mat and imagelabels.mat all come from the official dataset
download. Once they are in place, build the CSV split manifests:
python code/prepare_data.py
This creates data/train.csv, data/val.csv and data/test.csv. The training
code reads images from data/jpg/ and the split from those CSV files, so this
step must be done before any training.
There are two ways to run everything.
Open run_all.ipynb and run the cells in order. The notebook prepares the data,
runs every experiment, evaluates the checkpoints and builds the figures, so you
can watch the whole pipeline step by step. The data must still be placed in
data/ first, as described above.
Run the scripts directly. The dataset must already be prepared (see above).
Baseline — pretrained ResNet-18
python code/train.py --model resnet18 --pretrained \
--epochs 25 --lr-head 1e-3 --lr-backbone 1e-4 \
--run-name resnet18_baseline
Hyperparameter sweep — new-layer learning rate
python code/train.py --model resnet18 --pretrained --lr-head 1e-2 --lr-backbone 1e-4 --epochs 25 --run-name sweep_lr1e-2
python code/train.py --model resnet18 --pretrained --lr-head 1e-3 --lr-backbone 1e-4 --epochs 25 --run-name sweep_lr1e-3
python code/train.py --model resnet18 --pretrained --lr-head 1e-4 --lr-backbone 1e-4 --epochs 25 --run-name sweep_lr1e-4
From scratch — no pretraining
python code/train.py --model resnet18 --no-pretrained \
--epochs 60 --lr-head 1e-2 \
--run-name resnet18_scratch
Attention — ResNet-18 with SE blocks
python code/train.py --model resnet18-se --pretrained --epochs 25 --run-name resnet18_se
Evaluate a saved checkpoint
python code/evaluate.py --checkpoint checkpoints/resnet18_baseline.pth --model resnet18
Build all figures for the report
python code/plot_results.py
Each training run writes a per-epoch log to logs/<run-name>.csv and saves the
best model to checkpoints/<run-name>.pth.