AI Hints
Home›Deep Learning Tutorial›Famous Architectures
Deep Learning · Lesson 25 of 92

Data Augmentation

More data for free.

⏱ 2 min read▶ Video at 51:27🎓 Free
Watch this lesson in the Deep Learning courseWatch on YouTube ↗Full Deep Learning course

More data is the best cure for overfitting. But collecting and labelling images is expensive. Here's a neat trick. A cat flipped from left to right is still a cat. Slightly cropped, or a little brighter, it's still a cat. So from one photo, we can make endless new training examples, for free.

Data Augmentation
From the video: Data Augmentation
  • More data costs money
  • A flipped cat is still a cat
  • Endless examples for free

One photo, many views

Torchvision has a toolbox of these transforms. We compose three. A random flip, a random crop, and random colour changes. Run it. Here's one original photo, and five views of it. Each time an image is loaded for training, the model gets a slightly different version. So it can't memorise. It has to learn what really makes this a truck. Note that we only do this for training, never for testing.

augment.pypython
import torch
from torchvision import datasets, transforms
from torchvision.transforms import v2
import matplotlib.pyplot as plt

image = datasets.CIFAR10("data", train=False, download=True)[3][0]
aug = v2.Compose([v2.RandomHorizontalFlip(),
                  v2.RandomResizedCrop(32, scale=(0.6, 1.0)),
                  v2.ColorJitter(0.4, 0.4, 0.4)])

fig, ax = plt.subplots(1, 6, figsize=(10, 2))
ax[0].imshow(image); ax[0].set_title("Original")
torch.manual_seed(1)
for a in ax[1:]:
    a.imshow(aug(image))
for a in ax: a.axis("off")
plt.tight_layout()
plt.savefig("augment.png", dpi=120)
print("Five new training images from one photo")
Output
Five new training images from one photo

Choosing augmentations

Think about what stays true. Flipping is fine for animals, but not for digits, where a flipped two isn't a two. Rotation is fine for satellite images, but a bit silly for street signs. Colour jitter is fine, unless colour is the answer. Strong modern recipes like RandAugment, MixUp, and CutMix go much further, and blend images together. Always ask, does the label stay true?

Flips and cropsthe safe defaults
Rotationdepends on the task
Colour jitterunless colour matters
MixUp, CutMixblend images together

A real image classifier

Let's bring this all together, on real colour photos of planes, cars, birds, and more. The model uses three blocks with batch norm, global pooling, and dropout. The data uses crops and flips. We train on twelve thousand images, for speed. Run it. Accuracy climbs steadily, on a hard ten class problem, with just a few epochs and a small network. Aria can now recognise real objects in real photos. That's a big milestone.

cifar.pypython
import torch
from torch import nn
from torchvision import datasets
from torchvision.transforms import v2

root = "data"
norm = v2.Compose([v2.ToImage(), v2.ToDtype(torch.float32, scale=True),
                   v2.Normalize([0.49, 0.48, 0.45], [0.25, 0.24, 0.26])])
aug = v2.Compose([v2.RandomCrop(32, padding=4), v2.RandomHorizontalFlip(), norm])
train = datasets.CIFAR10(root, train=True, download=True, transform=aug)
test = datasets.CIFAR10(root, train=False, download=True, transform=norm)
train = torch.utils.data.Subset(train, range(12000))
test = torch.utils.data.Subset(test, range(2000))

def block(i, o):
    return nn.Sequential(nn.Conv2d(i, o, 3, padding=1), nn.BatchNorm2d(o),
                         nn.ReLU(), nn.MaxPool2d(2))

model = nn.Sequential(block(3, 32), block(32, 64), block(64, 128),
                      nn.AdaptiveAvgPool2d(1), nn.Flatten(),
                      nn.Dropout(0.2), nn.Linear(128, 10))
opt = torch.optim.AdamW(model.parameters(), lr=2e-3, weight_decay=0.01)
dl = torch.utils.data.DataLoader(train, batch_size=128, shuffle=True)
tl = torch.utils.data.DataLoader(test, batch_size=500)

for epoch in range(1, 7):
    model.train()
    for x, y in dl:
        loss = nn.functional.cross_entropy(model(x), y)
        opt.zero_grad(); loss.backward(); opt.step()
    if epoch % 2 == 0:
        model.eval()
        hits = 0
        with torch.no_grad():
            for x, y in tl:
                hits += (model(x).argmax(1) == y).sum().item()
        print(f"epoch {epoch}  accuracy {hits / len(test):.3f}")
Output
epoch 2  accuracy 0.443
epoch 4  accuracy 0.533
epoch 6  accuracy 0.540

Summary

Augmentation gives you free data, and it's one of the strongest tools there is. Aria can now see. But there's a problem with sight alone. The world doesn't arrive as single pictures. Language, speech, and video all come in sequences. Next, teaching networks to remember.

Key takeaways
  • Augment training data only
  • Ask: is the label still true?
  • Aria can now see
Next up: Sequences and Memory — recurrent neural networks