Machine Learning
Preparing data
Convert image data to tensors.
Project: horizontal and vertical lines
In this project we'll teach a small CNN to tell horizontal and vertical lines apart in 16×16 grey images. We generate the data ourselves: a thick line through the middle on a lightly noisy background. Class 0 is a horizontal line, class 1 a vertical one:
X = torch.rand(n, 1, 16, 16) * 0.3 # noisy background
# class 0: X[k, 0, 7:9, :] += 1 -> horizontal band
# class 1: X[k, 0, :, 7:9] += 1 -> vertical band
Synthetic data is a good way to quickly check that the code and the shapes are right before moving to a real image set.
Checking the data
Before training the data is checked: the shape, the class balance and whether an example really carries the expected pattern. For a horizontal line the mean of the middle rows is high; for a vertical one, that of the middle columns:
print(X_train.shape, torch.bincount(y_train).tolist())
k = (y_train == 0).nonzero()[0].item() # first horizontal example
print(X_train[k, 0, 7:9].mean().item() > X_train[k, 0, :, 7:9].mean().item())
Because the classes are roughly balanced, accuracy is a meaningful metric here.
Exercise Inspect the data
Print the shape of the training data. On one line print that for the first horizontal example the mean of the middle rows is larger than that of the middle columns, and the opposite for the first vertical example.
Show example solution
import torch
from torch import nn
torch.manual_seed(0)
def veri(n):
X = torch.rand(n, 1, 16, 16) * 0.3
y = torch.randint(0, 2, (n,))
for k in range(n):
if y[k] == 0:
X[k, 0, 7:9, :] += 1.0
else:
X[k, 0, :, 7:9] += 1.0
return X, y
X_train, y_train = veri(256)
X_test, y_test = veri(64)
print(X_train.shape)
k0 = (y_train == 0).nonzero()[0].item()
k1 = (y_train == 1).nonzero()[0].item()
a = X_train[k0, 0, 7:9].mean() > X_train[k0, 0, :, 7:9].mean()
b = X_train[k1, 0, :, 7:9].mean() > X_train[k1, 0, 7:9].mean()
print(a.item(), b.item())
Test yourself
-
Why is the image tensor's shape (n, 1, 16, 16)?
- It was chosen at random
- For the linear layer
- For an RNN
- Conv2d wants (example, channel, height, width); a grey image has one channel
Show answer
Conv2d wants (example, channel, height, width); a grey image has one channel — For a colour image the channel count would be 3.
-
Get the class counts.
print(torch.____(y_train).tolist())
Show answer
print(torch.bincount(y_train).tolist())
-
Match the data pieces.
- torch.rand(...) * 0.3
- Noisy background
- X[k, 0, 7:9, :]
- Horizontal band
- X[k, 0, :, 7:9]
- Vertical band
- torch.randint(0, 2, (n,))
- Random labels
Next lesson: CNN model