FastAI Image Classification

by Gilbert Tanner on Feb 13, 2019

FastAI Image Classification

FastAi is a research lab with the mission of making AI accessible by providing an easy to use library build on top of PyTorch, as well as exceptionally good tutorials/courses like the Practical Deep Learning for Coders course which I am currently enrolled in.

In their courses, they use a “top-down” teaching approach, which directly throws you into coding and lets you solve problems (real problems not just practice once), rather than teaching the material “bottom up” by explaining the theory first. This allows for a rapid learning process with lots of success moments.

The FastAi library is a high-level library build on PyTorch, which allows us to build models using only a few lines of code. Furthermore it implements some of the newest state-of-the-art technics taken from research papers that allow you to get state-of-the-art results on almost any type of problem.

An example of this is the differential learning rates feature, which allows us to perform transfer learning with less code and time by giving us the ability to set different learning rates for different parts in the network. This allows us to train the earlier layers less than the latter layers.

In this article, we will learn how to use FastAI to work through a computer vision example. After this article you will know how to perform the following steps:

  1. Download image dataset
  2. Load and view your data
  3. Create and train a model
  4. Clear your dataset
  5. Interpret the results

If you prefer a visual tutorial you can check out my video on the topic.

FastAI Image Classification Video


The FastAI library can be installed by either using conda or pip.

conda install -c pytorch pytorch-cpu torchvision
conda install -c fastai fastai


pip install
pip install fastai

For more information about the installation visit the official guide.

If you successfully installed the library you can now import the vision module by typing:

from import *

Downloading image data

The FastAI library provides a lot of different datasets which can be loaded in directly, but it also provides functionality for downloading images given a file containing the URLs of these images.

In order to get the URLs, we will navigate to Google Images, search for our category of choice, scroll down until enough images are loaded and then execute the following javascript code from the developer console.

Update new code (

let urls = Array.from(document.querySelectorAll('.rg_i')).map(el=> el.hasAttribute('data-src')?el.getAttribute('data-src'):el.getAttribute('data-iurl'));
let hiddenElement = document.createElement('a');
hiddenElement.href = 'data:text/csv;charset=utf-8,' + encodeURI(urls.filter((value, index, arr) => { return value != null}).join('\n')); = '_blank'; = 'myFile.csv';;

For this article, I will create an animal classifier which can distinguish between cats, cows, dogs, and horses. To do that I searched for all four of them and use the above command to save a csv file containing the links.

After we downloaded the csv files we can download the data using the download_images method.

path = Path('<path>')

for file, folder in [('Cats.csv', 'Cats'), ('Cows.csv', 'Cows'), 
                     ('Dogs.csv', 'Dogs'), ('Horses.csv', 'Horses')]:
    dest = path/folder # path + '/' + folder
    dest.mkdir(parents=True, exist_ok=True)
    download_images(path/file, dest)

We can verify that we don’t have any corrupt images using the verify_images method.

for folder in ('Cats', 'Cows', 'Dogs', 'Horses'):
    verify_images(path/folder, delete=True, max_size=500)

This will try if any image in the given folder can be opened and has n_channels (defaults to 3). If one of these conditions isn’t given the image will be deleted.

Loading and viewing data

FastAI has specific data objects called databunches which are needed to train a model. These databunches can be created in two main ways.

The first way is to use problem-specific methods like the ImageDataBunch.from_folder which can be used to load data that has the following structure.


These methods are easy for specific folder structures but can’t be used for others so FastAI has another way of loading in data called the data block api which gives you more options by isolating the underlying parts of that process in separate blocks. More information on both methods can be found in the FastAi docs.

Loading in our data:

data = ImageDataBunch.from_folder(path, train='.', valid_pct=0.2,
                                  ds_tfms=get_transforms(), size=224, num_workers=4).normalize(imagenet_stats)

Now we can use the data object to get more information about or data.


Out: ['Cats', 'Cows', 'Dogs', 'Horses']

We can show a random batch of images using the show_batch method.

data.show_batch(rows=3, figsize=(7, 8))
Random batch of images
Figure 1: Random batch of images

Creating a model and initial training

The FastAI library is designed to let you create models (FastAi calls them learners) with only a few lines of code. They provide a method called create_cnn, which can be used to create a convolutional neural network.

The method needs two arguments, the data, and the architecture, but also supports many other parameters that can be used to customize the model for a given problem.

from fastai.metrics import error_rate # 1 - accuracy
learn = create_cnn(data, models.resnet34, metrics=error_rate)

The created model uses the resnet34 architecture, with weights pretrained on the imagenet dataset.

By default, only the fully connected layers at the top are unfrozen (can be trained), which if you are familiar with transfer learning makes perfect sense.

To train the layers we can use the fit or fit_one_cycle method. The fit method is the “normal” way of training a neural net with a constant learning rate, whilst the fit_one_cycle method uses something called the 1 cycle policy, which basically changes the learning rate over time to achieve better results.

defaults.device = torch.device('cuda') # makes sure the gpu is used
Training output
Figure 2: Training output

Now that the fully-connected layers are well trained we can unfreeze the other layers and train the whole network.

As mentioned at the start of the article, FastAI provides another technic to enhance transfer learning called differential learning rates, which allows us to set different learning rates for different parts in the network.

To find the perfect learning rates we can use the lr_find and recorder.plot methods which create a plot that relates the learning rate with the loss.

learn.unfreeze() # must be done before calling lr_find
Learning rate plot
Figure 3: Learning rate plot

Here we are searching for the  point with the steepest downward slope that still has a high value, which in this case is around 3e-5. Interpreting this plot takes a lot of intuition and Jeremy Howard talks a lot about it in the first few lessons of the course.

To now train the model using differential learning rates we need to pass the max_lr argument to the fit_one_cycle method.

learn.fit_one_cycle(4, max_lr=slice(3e-5, 3e-4))
Training output
Figure 4: Training output

The model can now be saved using the save method.'animal-detection-stage-1')

Cleaning data

FastAI also provides functionality for cleaning your data using Jupyter widgets. The ImageCleaner class displays images for relabeling or deletion and saves changes in path as 'cleaned.csv'.

To use ImageCleaner we must first use DatasetFormatter().from_toplosses to get the suggested indices for misclassified images.

from fastai.widgets import *

ds, idxs = DatasetFormatter().from_toplosses(learn)
ImageCleaner(ds, idxs, path)
Image Cleaner
Figure 5: Image Cleaner

Final training

The results of the cleaning are saved as cleaned.csv which can now be used to load in the data.

df = pd.read_csv(path/'cleaned.csv', header='infer')

db = (ImageItemList.from_df(df, path)
                   .transform(get_transforms(), size=224)
CSV Structure
Figure 6: CSV structure

We can now print out the lengths of both the new and old dataset to see how many images we deleted.

print(data.classes, data.c, len(data.train_ds), len(data.valid_ds))
print(db.classes, db.c, len(db.train_ds), len(db.valid_ds))

Old:['Cats', 'Cows', 'Dogs', 'Horses'] 4 1181 295
New:['Cats', 'Cows', 'Dogs', 'Horses'] 4 923 230

We can also show a random batch again.

Random batch of images
Figure 7: Random batch of images

Now we can apply the same training steps as above but using the new data. We are also going to use the saved weights so we don’t need to start from scratch.

learn.load('animal-detection-stage-1') # loading the weights = db # replacing the data




learn.fit_one_cycle(4, max_lr=slice(3e-5, 3e-4))'animal-detection-stage-2')


Lastly, we can use FastAIs ClassificationInterpretation class to interpret our results. To create an interpretation object we need to call the from_learner method and pass it our learner/model. Then we can use methods like plot_confusion_matrix, plot_top_losses or most_confused.

interp = ClassificationInterpretation.from_learner(learn)

Plot confusion matrix:

Confusion matrix
Figure 8: Confusion matrix

Plot top losses:

interp.plot_top_losses(9, figsize=(15,15))
Top losses plot
Figure 9: Top losses plot


FastAi is a research lab with the mission of making AI accessible by providing an easy to use library build on PyTorch, as well as exceptionally good tutorials/courses.

The FastAi library is a high-level library build on PyTorch which allows for easy prototyping and gives you access to a lot of state-of-the-art methods/techniques.

If you liked this article consider subscribing to my Youtube Channel and following me on social media.

The code covered in this article is available as a Github Repository.

If you have any questions, recommendations or critiques, I can be reached via Twitter or the comment section.