Overview
A deep learning image classifier that identifies 102 species of flowers, built as the capstone project of the Udacity AI Programming with Python Nanodegree. The model uses VGG16 pretrained on ImageNet as a feature extractor, with a custom classifier trained on the Oxford 102 Flower Dataset.
Approach
Instead of training a neural network from scratch, I used transfer learning: the convolutional layers of VGG16 are frozen and act as a fixed feature extractor, while only the final classifier layers are trained on the flower dataset. This makes training fast and achieves strong accuracy even on a relatively small dataset.
- Backbone: VGG16 pretrained on ImageNet, all convolutional weights frozen
- Custom classifier: Linear(25088→512) → ReLU → Dropout(0.2) → Linear(512→102) → LogSoftmax
- Data augmentation: random resized crop and horizontal flip during training to reduce overfitting
- Normalization: ImageNet mean and std ([0.485, 0.456, 0.406] / [0.229, 0.224, 0.225])
- Loss / Optimizer: NLLLoss with Adam (lr=0.001), trained for 5 epochs on GPU
Command-Line Interface
Beyond the notebook, the project ships as two standalone CLI scripts:
train.py flowers/ --arch vgg16 --epochs 5 --gputrains on any ImageFolder dataset and saves a checkpointpredict.py image.jpg checkpoint.pth --top_k 5 --category_names cat_to_name.jsonloads a checkpoint and prints ranked predictions
What I Learned
- The full PyTorch training loop: ImageFolder → DataLoader → forward pass → loss → backward → optimizer step
- Why transfer learning works: the pretrained network already detects edges, textures, and shapes fine-tuning just maps those features to new classes
- How to save and restore model checkpoints including the class-to-index mapping
- Converting a Jupyter notebook into reusable CLI scripts with
argparse - The difference between training accuracy and validation accuracy, and why validation is the number that matters
Notebook
Full implementation below, from data loading through inference: