Photo mosaic.
Photo mosaic. (source: Pixabay).

For the last eight months, I have spent a lot of time trying to absorb as much as I can about machine learning. I am constantly amazed at the variety of people I meet on online MOOCs in this small but quickly growing community, from quantum researchers at Fermilab to Tesla-driving Silicon Valley CEOs. Lately, I have been putting a lot of my focus into the open source software TensorFlow, and this tutorial is the result of that.

I feel like a lot of machine learning tutorials are geared toward Mac. One major advantage of using Linux is it’s free and it supports using TensorFlow with your GPU. The accelerated parallel computing power of GPUs are one of the reasons for such major advancements in machine learning. You don’t need cutting-edge technology to build a fast image classifier; my computer and graphic card cost me less than $400 USD.

In this tutorial, I am going to walk you through how I learned to train my own image classifier on Ubuntu with a GPU. This tutorial is very similar to Pete Warden’s TensorFlow for Poets, but I did things a little differently. I am going to assume that you have TensorFlow and Bazel installed and have cloned the latest TensorFlow release in your home directory. If you have not yet done that, you can follow a tutorial on my blog. If you don’t have a compatible GPU, you can still follow this tutorial; it will just take longer.

The overall process is extremely simple and can be broken into four main steps.

  1. Collecting the training images
  2. Training a graph/model using TensorFlow and the Inception model
  3. Building the script that will classify new images using your graph
  4. Testing the script by classifying new images

I decided to train my classifier on five birds of prey. Using birds of prey wasn’t a random decision. For two years, I worked for The Raptors, an educational center and wildlife management organization in Duncan, British Columbia, and I’ve had a long-standing passion for these powerful and mythical creatures. As the ultimate challenge, I pitted my classifier against Cornell Ornithology Lab's Merlin ID tool. Since writing this article, the lab has updated its site with this note: “Merlin Photo ID is temporarily down for maintenance and upgrades. … The Cornell Lab of Ornithology and Visipedia are collaborating to develop computer vision technology to identify birds in photos.” Without a doubt, I suspect that they are upgrading their (now unavailable) Merlin system to a modern machine learning classifier.

Collecting training images

I began by gathering about 100 photos of each bird from The Raptors’s Facebook page and from web searches. I was able to build a set of photos with a good mix of the birds in many different environments and positions. It is ideal for an image classifier to have at least 100 photos in varying scenarios and backgrounds in order for it to generalize well. There are also ways to distort existing photos to make more training examples, but this can slow your training process to a crawl. Keep in mind that we don’t need thousands of examples to train our model, because TensorFlow will retrain a new model using trained feature detectors from the previously trained Inception model.

As an additional experiment, about 10% of the pictures I used were of juvenile birds of each species. I was curious if the classifier could find the similarities between a juvenile bird and a mature one.

Once I had the right number and types of images, I created a folder in my TensorFlow directory:

$ cd ~/tensorflow

$ mkdir tf_files && cd tf_files && mkdir bird_photos && cd bird_photos

$ mkdir baldeagle goldeneagle peregrine saker vulture

This is what my directory looked like:

TensorFlow directory
Figure 1. Screenshot courtesy of Justin Francis.

I then moved the images into their appropriate folders. The script accepted PNG, JPG, GIF & TIF images, but I noticed in order to prevent an error, I had to rename one file that had a lot of symbols in its name.

Training the model

I then trained a new model and associated labels using a built-in python script from the TensorFlow git clone. The original graph we are retraining took Google researchers two weeks to build on a desktop with eight NVidia Tesla K40s.

$ cd ~/tensorflow

$ python tensorflow/examples/image_retraining/retrain.py \
--bottleneck_dir=tf_files/bottlenecks \
--model_dir=tf_files/inception \
--output_graph=tf_files/retrained_graph.pb \
--output_labels=tf_files/retrained_labels.txt \
--image_dir tf_files/bird_photos

Since I had TensorFlow installed with GPU support, training my model took less than 10 minutes. If I had done this on my old Xeon CPU, it probably would have taken me all day! Here are the results:

TensorFlow classifer results 1
Figure 2. Screenshot courtesy of Justin Francis.

My TensorFlow model got a final test accuracy of 91.2%. I found this very impressive given the wide variety of photos I had used.

Build the classifier

Up to this point, I took the Inception graph and retrained it using my photos. Next, I built my image classifier from the TensorFlow git clone using Bazel. (Don’t close the terminal or you will need to rebuild.)

$ bazel build tensorflow/examples/label_image:label_image

Test the classifier

Now the fun part—testing the classifier against a new set of images. To make things easy, I put my test photos in my tf_files folder.

$ bazel-bin/tensorflow/examples/label_image/label_image \
--graph=tf_files/retrained_graph.pb \
--labels=tf_files/retrained_labels.txt \
--output_layer=final_result \
--image=tf_files/bird.jpg #This is the test image

First, I tried to classify a picture that I could immediately identify as a saker falcon:

saker falcon
Figure 3. Mature saker falcon, DickDaniels on Wikimedia Commons.

TensorFlow agreed!

TensorFlow classifer results 2
Figure 4. Screenshot courtesy of Justin Francis.

Next, I tried a trickier juvenile peregrine falcon (left in the image below) that I had not used in my training data. A juvenile peregrine has front plumage similar to a saker but will develop a more striped belly, yellow beak, and a paler lower neck as it matures.

Spinus Peregrine FalconPeregrine Falcon
Figure 5. On the left: Juvenile peregrine falcon, Spinus Nature Photography on Wikimedia Commons. On the right: Peregrine falcon, Norbert Fischer on Wikimedia Commons.

To my amazement the classifier detected the juvenile peregrine with quite high accuracy:

TensorFlow classifier results 3
Figure 6. Screenshot courtesy of Justin Francis.

For my last example, I used a bird that humans often misclassify: the juvenile bald eagle. People often mistake it for a golden eagle because it does not have solid white plumage on its head and tail. I trained my classifier with about 10% photos of juvenile eagles.

Newly Fledged Juvenile Bald Eagle
Figure 7. Newly fledged juvenile bald eagle, KetaDesign on Wikimedia Commons.

Seems like my classifier is not exceeding ornithologist-level intelligence yet:

TensorFlow classifier results 4
Figure 8. Screenshot courtesy of Justin Francis.

I was especially surprised that “vulture” was its second guess and not bald eagle. This may be due to the fact that many of my vulture pictures were taken from a similar view.

What about Merlin? Its first choice was spot on with a very reasonable second choice.

Cornell Ornithology Lab's Merlin ID tool
Figure 9. Screenshot courtesy of Justin Francis.

This is the only photo that Merlin beat me on. But with enough training data, I’m fully confident my classifier could learn to distinguish adult bald eagles, juvenile bald eagles, and golden eagles. I, of course, would need a separate juvenile bald eagle folder with additional images.

I had a lot of fun training and experimenting with this classifier, and I hope this post helps you make your own classifier, too. The possibilities for researchers and enthusiasts are endless. Feel free to tag me @wagonhelm or #TensorFlow on Twitter and show off what you created.

Article image: Photo mosaic. (source: Pixabay).