Learn data science and machine learning by building real-world projects on Jovian
In [2]:
!pip install jovian --upgrade --quiet
In [3]:
import jovian

Building A CNN to Classify Bird Species

Final project for the zerotogans course

In [4]:
project_name = "bird-classification-cnn"
In [4]:
import os
from random import randrange
import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.utils.data import DataLoader
import torchvision
import torchvision.models as models
from torchvision.datasets.utils import download_url
from torchvision.datasets import ImageFolder
import torchvision.transforms as tt
from torchvision.utils import make_grid
import matplotlib.pyplot as plt
%matplotlib inline
In [5]:
data_dir = '../input/100-bird-species'
species = os.listdir(data_dir + "/train")
num_classes = len(species)
print("num species:", num_classes)
print({cls: len(os.listdir(data_dir + f"/train/{cls}/")) for cls in sorted(species)})
num species: 200 {'AFRICAN FIREFINCH': 140, 'ALBATROSS': 97, 'ALEXANDRINE PARAKEET': 165, 'AMERICAN AVOCET': 179, 'AMERICAN BITTERN': 170, 'AMERICAN COOT': 158, 'AMERICAN GOLDFINCH': 133, 'AMERICAN KESTREL': 130, 'AMERICAN PIPIT': 179, 'AMERICAN REDSTART': 139, 'ANHINGA': 147, 'ANNAS HUMMINGBIRD': 139, 'ANTBIRD': 150, 'ARARIPE MANAKIN': 105, 'BALD EAGLE': 160, 'BALTIMORE ORIOLE': 137, 'BANANAQUIT': 106, 'BAR-TAILED GODWIT': 114, 'BARN OWL': 119, 'BARN SWALLOW': 132, 'BAY-BREASTED WARBLER': 143, 'BEARDED BARBET': 160, 'BELTED KINGFISHER': 125, 'BIRD OF PARADISE': 104, 'BLACK FRANCOLIN': 131, 'BLACK SKIMMER': 111, 'BLACK SWAN': 112, 'BLACK THROATED WARBLER': 135, 'BLACK VULTURE': 126, 'BLACK-CAPPED CHICKADEE': 133, 'BLACK-NECKED GREBE': 105, 'BLACK-THROATED SPARROW': 168, 'BLACKBURNIAM WARBLER': 134, 'BLUE GROUSE': 185, 'BLUE HERON': 104, 'BOBOLINK': 157, 'BROWN NOODY': 129, 'BROWN THRASHER': 99, 'CACTUS WREN': 122, 'CALIFORNIA CONDOR': 153, 'CALIFORNIA GULL': 109, 'CALIFORNIA QUAIL': 115, 'CANARY': 160, 'CAPE MAY WARBLER': 145, 'CAPUCHINBIRD': 133, 'CARMINE BEE-EATER': 121, 'CASPIAN TERN': 213, 'CASSOWARY': 114, 'CHARA DE COLLAR': 104, 'CHIPPING SPARROW': 115, 'CINNAMON TEAL': 117, 'COCK OF THE ROCK': 124, 'COCKATOO': 166, 'COMMON GRACKLE': 177, 'COMMON HOUSE MARTIN': 127, 'COMMON LOON': 109, 'COMMON POORWILL': 161, 'COMMON STARLING': 141, 'COUCHS KINGBIRD': 140, 'CRESTED AUKLET': 106, 'CRESTED CARACARA': 146, 'CROW': 107, 'CROWNED PIGEON': 118, 'CUBAN TODY': 122, 'CURL CRESTED ARACURI': 137, 'D-ARNAUDS BARBET': 233, 'DARK EYED JUNCO': 203, 'DOWNY WOODPECKER': 127, 'EASTERN BLUEBIRD': 128, 'EASTERN MEADOWLARK': 190, 'EASTERN ROSELLA': 118, 'EASTERN TOWEE': 127, 'ELEGANT TROGON': 144, 'ELLIOTS PHEASANT': 148, 'EMPEROR PENGUIN': 129, 'EMU': 106, 'EURASIAN MAGPIE': 155, 'EVENING GROSBEAK': 144, 'FLAME TANAGER': 177, 'FLAMINGO': 92, 'FRIGATE': 105, 'GILA WOODPECKER': 146, 'GILDED FLICKER': 139, 'GLOSSY IBIS': 175, 'GOLD WING WARBLER': 128, 'GOLDEN CHEEKED WARBLER': 176, 'GOLDEN CHLOROPHONIA': 135, 'GOLDEN EAGLE': 87, 'GOLDEN PHEASANT': 107, 'GOULDIAN FINCH': 130, 'GRAY CATBIRD': 155, 'GRAY PARTRIDGE': 103, 'GREEN JAY': 156, 'GREY PLOVER': 120, 'GUINEAFOWL': 104, 'HAWAIIAN GOOSE': 113, 'HOODED MERGANSER': 135, 'HOOPOES': 125, 'HORNBILL': 122, 'HOUSE FINCH': 249, 'HOUSE SPARROW': 125, 'HYACINTH MACAW': 101, 'IMPERIAL SHAQ': 144, 'INCA TERN': 118, 'INDIGO BUNTING': 147, 'JABIRU': 143, 'JAVAN MAGPIE': 109, 'KILLDEAR': 175, 'KING VULTURE': 136, 'LARK BUNTING': 117, 'LILAC ROLLER': 138, 'LONG-EARED OWL': 106, 'MALACHITE KINGFISHER': 163, 'MALEO': 120, 'MALLARD DUCK': 135, 'MANDRIN DUCK': 130, 'MARABOU STORK': 197, 'MASKED BOOBY': 132, 'MIKADO PHEASANT': 102, 'MOURNING DOVE': 126, 'MYNA': 141, 'NICOBAR PIGEON': 129, 'NORTHERN CARDINAL': 101, 'NORTHERN FLICKER': 139, 'NORTHERN GANNET': 145, 'NORTHERN GOSHAWK': 112, 'NORTHERN JACANA': 156, 'NORTHERN MOCKINGBIRD': 140, 'NORTHERN PARULA': 196, 'NORTHERN RED BISHOP': 135, 'OCELLATED TURKEY': 118, 'OSPREY': 127, 'OSTRICH': 97, 'PAINTED BUNTIG': 163, 'PARADISE TANAGER': 176, 'PARUS MAJOR': 122, 'PEACOCK': 156, 'PELICAN': 90, 'PEREGRINE FALCON': 126, 'PINK ROBIN': 128, 'PUFFIN': 124, 'PURPLE FINCH': 128, 'PURPLE GALLINULE': 128, 'PURPLE MARTIN': 109, 'PURPLE SWAMPHEN': 105, 'QUETZAL': 152, 'RAINBOW LORIKEET': 141, 'RAZORBILL': 194, 'RED FACED CORMORANT': 127, 'RED FACED WARBLER': 167, 'RED HEADED DUCK': 103, 'RED HEADED WOODPECKER': 133, 'RED HONEY CREEPER': 132, 'RED THROATED BEE EATER': 130, 'RED WINGED BLACKBIRD': 93, 'RED WISKERED BULBUL': 123, 'RING-BILLED GULL': 153, 'RING-NECKED PHEASANT': 97, 'ROADRUNNER': 107, 'ROBIN': 95, 'ROCK DOVE': 132, 'ROSY FACED LOVEBIRD': 139, 'ROUGH LEG BUZZARD': 96, 'RUBY THROATED HUMMINGBIRD': 135, 'RUFOUS KINGFISHER': 156, 'RUFUOS MOTMOT': 189, 'SAND MARTIN': 95, 'SCARLET IBIS': 91, 'SCARLET MACAW': 105, 'SHOEBILL': 175, 'SNOWY EGRET': 96, 'SNOWY OWL': 161, 'SORA': 300, 'SPANGLED COTINGA': 112, 'SPLENDID WREN': 121, 'SPOONBILL': 192, 'STEAMER DUCK': 109, 'STORK BILLED KINGFISHER': 135, 'STRAWBERRY FINCH': 167, 'TAIWAN MAGPIE': 136, 'TEAL DUCK': 99, 'TIT MOUSE': 146, 'TOUCHAN': 136, 'TOWNSENDS WARBLER': 165, 'TREE SWALLOW': 181, 'TRUMPTER SWAN': 137, 'TURKEY VULTURE': 149, 'TURQUOISE MOTMOT': 156, 'VARIED THRUSH': 193, 'VENEZUELIAN TROUPIAL': 127, 'VERMILION FLYCATHER': 155, 'VIOLET GREEN SWALLOW': 201, 'WATTLED CURASSOW': 138, 'WHITE CHEEKED TURACO': 153, 'WHITE NECKED RAVEN': 112, 'WHITE TAILED TROPIC': 175, 'WILD TURKEY': 144, 'WILSONS BIRD OF PARADISE': 126, 'WOOD DUCK': 214, 'YELLOW HEADED BLACKBIRD': 159}
In [ ]:
# @todo - data normilization and augmentation
In [8]:
transform = tt.Compose(
    [
        tt.ToTensor(), 
    ]
)

# Create datasets
train_ds = ImageFolder(data_dir+'/train', transform)
valid_ds = ImageFolder(data_dir+'/test', transform)

# set the batch size
batch_size = 64

train_dl = DataLoader(train_ds, batch_size, shuffle=True, num_workers=3, pin_memory=True)
valid_dl = DataLoader(valid_ds, batch_size*2, num_workers=2, pin_memory=True)

classes = valid_ds.classes
In [11]:
def show_example(data):
    [img, label] = data
    print(classes[label])
    plt.imshow(img.permute(1, 2, 0))
    
# show a bird - hi bird!
image_number = randrange(20000)
show_example(train_ds[image_number])
BLACK THROATED WARBLER
Notebook Image
In [12]:
def show_batch(dl):
    for images, labels in dl:
        fig, ax = plt.subplots(figsize=(12, 12))
        ax.set_xticks([]); ax.set_yticks([])
        ax.imshow(make_grid(images[:64], nrow=8).permute(1, 2, 0))
        break
In [13]:
show_batch(train_dl)