Building End-to-End Computer Vision Applications with Fastai
Computer vision has seen remarkable progress in recent years, with deep learning models achieving superhuman performance on tasks like image classification, object detection, and semantic segmentation. Thanks to the availability of powerful open source deep learning libraries, it‘s now possible for developers to quickly build and deploy state-of-the-art computer vision applications without being an expert in neural networks.
In this blog post, we‘ll walk through how to build an end-to-end image classification application using fastai, a cutting-edge deep learning library. Fastai provides high-level APIs for quickly training models using best practices, while still providing low-level access to customize models as needed. By the end of this post, you‘ll be able to train a highly accurate classifier and deploy it in an application.
The Fastai Deep Learning Library
Fastai is a deep learning library built on top of PyTorch that allows developers to train state-of-the-art models with minimal code. Some key features of fastai include:
- High-level APIs for common tasks like image classification, text classification, tabular modeling, and recommendation systems
- Easy access to best practices like learning rate finding, discriminative layer training, mixed precision training, and progressive resizing
- Customizable models and low-level access to PyTorch for fine-grained control
- Rich documentation and tutorials for learning
- Interoperability with Hugging Face transformers, Weights & Biases, and other popular libraries
Fastai adopts a "layered" approach where high-level APIs for training models are composed of modular, reusable, and customizable building blocks. The core APIs are:
- DataLoaders – prepare your data for model training by applying transforms and creating batches
- Learner – handles model training and inference by putting together an optimizer, a model, and data
- Metrics – evaluate your model performance during training and inference
- Callbacks – inject custom functionality into the training loop to monitor, debug, or tweak model training
With just these core components, you can develop a wide range of deep learning applications across different domains and tasks. Let‘s see how to use them to build an image classifier.
Prepare the Data
The first step in any machine learning project is to gather, clean, and prepare your data. For our example, we‘ll use the Oxford-IIIT Pet Dataset which has ~7,000 images of cats and dogs annotated with breed labels.
We can download this dataset directly using fastai‘s built-in dataset collection:
from fastai.vision.all import *
path = untar_data(URLs.PETS)
This downloads the data, extracts it, and returns a Path object with the directory containing the images.
Next, we need to tell fastai how to interpret the directory structure to create a DataLoaders object. We use fastai‘s DataBlock API to define the inputs (images) and outputs (labels):
pets = DataBlock(
blocks=(ImageBlock, CategoryBlock),
get_items=get_image_files,
splitter=RandomSplitter(seed=42),
get_y=using_attr(RegexLabeller(r‘(.+)_\d+.jpg$‘), ‘name‘),
item_tfms=[Resize(460), ToTensor],
batch_tfms=aug_transforms(size=224, min_scale=0.75)
)
dls = pets.dataloaders(path/"images")
There‘s a lot going on here, so let‘s break it down:
blocksspecifies the type of input (images) and output (categories)get_itemspoints to the input image filessplitterdefines how to split the data into training and validation setsget_yextracts the labels from the filenames using a regular expressionitem_tfmsresizes the images to a standard size and converts them to PyTorch tensorsbatch_tfmsperforms data augmentation on batches of images during training
The DataBlock defines a "recipe" for creating a DataLoaders object from a file path. The dataloaders method creates a training and validation set according to the block definitions.
With our data prepared, we‘re ready to train a model! But first, let‘s take a peek at our data:
dls.show_batch(max_n=9, figsize=(7,8))
This shows a batch of images along with their labels:

Find the Learning Rate
An important step before training any deep learning model is to find a good learning rate. The learning rate determines the size of the steps the optimizer takes to update the model weights. If the learning rate is too low, training will progress very slowly. If it‘s too high, the loss may fluctuate or even diverge.
Fastai provides a handy learning rate finder utility that trains the model for a few iterations while increasing the learning rate exponentially. By plotting the loss vs. learning rate, we can identify a good learning rate as the point with the steepest slope (strongest decrease in loss).
To use the learning rate finder, we first need to create a Learner object that combines our model, data, optimizer, and loss function:
learn = vision_learner(dls, resnet50, metrics=error_rate)
lr_min,lr_steep = learn.lr_find()
print(f"Suggested learning rates:\nMin numerically stable: {lr_min}\nSteepest point: {lr_steep}")
The vision_learner function is a shortcut that creates a Learner with an image classifier head on top of a pre-trained model, in this case a ResNet50. We pass in the DataLoaders object, the metrics to compute during training, and save the returned Learner object for later.
When we call lr_find, fastai trains the model for a few iterations while exponentially increasing the learning rate from 1e-7 to 10. We can plot the losses with learn.recorder.plot() to visualize:

The learning rate finder suggests two learning rates: the numerically minimum stable one (1e-5) and the "steepest" one with the strongest rate of decrease in the loss (1e-3). We‘ll use the latter since it will help the model converge faster.
Train the Model
Now we‘re ready to train our model! Since we‘re using a pre-trained model, we‘ll use transfer learning to quickly adapt the model to our dataset.
The basic idea is to:
- Freeze all the layers except the last classifier layer
- Train the classifier head for a few epochs with a high learning rate to quickly converge
- Unfreeze all layers and train the entire network at a lower learning rate to fine-tune
We can do this with fastai‘s fine_tune method:
learn.fine_tune(epochs=6, base_lr=1e-3, freeze_epochs=3)
This freezes the model for 3 epochs while training the classifier head at a learning rate of 1e-3, then unfreezes the model and trains all layers for 3 more epochs at a lower learning rate.
On a GPU, this fine-tuning process only takes a few minutes. Here‘s the output:
epoch train_loss valid_loss error_rate time
0 0.663807 0.185389 0.062622 00:05
1 0.458638 0.152183 0.047479 00:06
2 0.336021 0.128474 0.042607 00:06
3 0.219740 0.082140 0.015385 00:06
4 0.184726 0.075628 0.013746 00:08
5 0.175744 0.068064 0.017024 00:09
After just 6 epochs of training, our model is achieving 98.3% accuracy on the validation set! Let‘s see how well it does on some sample images:
learn.show_results()

Looking good! The model correctly classifies the breeds of cats and dogs in the sample images.
Evaluate the Model
To get a more comprehensive view of our model‘s performance, we can use fastai‘s ClassificationInterpretation class to generate a confusion matrix:
interp = ClassificationInterpretation.from_learner(learn)
interp.plot_confusion_matrix(figsize=(12,12), dpi=60)

The confusion matrix shows that the model performs well across all breeds, with only a few mistakes. The most confused breeds appear to be the Birman and Bombay cats and the Miniature Poodle and Toy Poodle dogs.
We can also plot the most wrong predictions with interp.plot_top_losses() to debug further:
Put the Model in Production
Now that we have a trained model, how can we use it in an application? Fastai provides an export method that saves the model as a serialized file:
learn.export(‘model.pkl‘)
This saves a pickled version of the Learner object that includes the model architecture and trained parameters. We can load this in a separate process with:
learn = load_learner(‘model.pkl‘)
img = PILImage.create(‘my-image.jpg‘)
pred,pred_idx,probs = learn.predict(img)
print(f"Prediction: {pred}; Probability: {probs[pred_idx]:.4f}")
This loads the Learner, creates an image from a file path, passes it through the model, and returns the predicted class, class index, and probabilities.
We can even deploy our trained model to a cloud endpoint on services like AWS Lambda, Google Cloud Functions, or Hugging Face Spaces without having to manage any infrastructure. Check out the FastAPI and Gradio tutorials to learn more.
Next Steps
In this post, we walked through the key steps of building an end-to-end image classification model with fastai:
- Preparing the data with
DataBlockandDataLoaders - Finding a good learning rate with the
lr_findutility - Training the model using transfer learning and fine-tuning
- Evaluating performance with a confusion matrix and top losses
- Exporting the model for production use
Of course, this just scratches the surface of what‘s possible with computer vision and deep learning. Here are some ideas to explore further:
- Try different architectures like EfficientNet, Vision Transformers, or ConvNeXt
- Experiment with more advanced augmentation techniques like MixUp or CutMix
- Leverage self-supervised learning to train on unlabeled data with techniques like DINO or BEiT
- Apply your model to tasks like multi-label classification, object detection, or segmentation
- Explore model distillation to compress the model for edge devices
- Deploy your model behind an API, build a demo app, or integrate into a product
I‘m really excited by the rapid progress in computer vision and how accessible state-of-the-art models have become thanks to libraries like fastai. Go build some cutting-edge applications!
Resources
- Fastai course – https://course.fast.ai/
- Fastai docs – https://docs.fast.ai/
- Fastai tutorials – https://tutorials.fast.ai/
- Fastai blog – https://www.fast.ai/topics/
- Practical Deep Learning for Coders with fastai and PyTorch (book) – https://www.oreilly.com/library/view/practical-deep-learning/9781492034858/