๐ŸŽ“ A1Learner
๐Ÿ”

PyTorch Training the Classifier

A multi-class classifier is a model that picks one class from three or more. It gives one score per class for each row, and the highest score wins.

Labels for three classes

torch.full builds one label block per class. torch.cat joins the blocks in order.

labels = torch.cat([torch.full((3,), i, dtype=torch.long)
                    for i in range(3)])
print(labels)

An MLP with three outputs

Two inputs enter, and three scores leave. One score belongs to each class.

torch.manual_seed(1)
model = nn.Sequential(
    nn.Linear(2, 16),
    nn.ReLU(),
    nn.Linear(16, 3),
)
points = torch.randn(4, 2)
print(model(points).shape)

Batches from a DataLoader

The loader cuts the dataset into batches. The last batch holds the leftover rows.

dataset = TensorDataset(torch.randn(10, 2),
                        torch.zeros(10, dtype=torch.long))
loader = DataLoader(dataset, batch_size=4)
for batch_points, batch_labels in loader:
    print(batch_points.shape, batch_labels.shape)

Example

import torch
from torch import nn
from torch.utils.data import DataLoader, TensorDataset

torch.manual_seed(0)

per_class = 60
centres = [torch.tensor([-3.0, -2.0]), torch.tensor([3.0, -2.0]),
           torch.tensor([0.0, 3.0])]
blobs = [torch.randn(per_class, 2) * 0.8 + centre for centre in centres]
points = torch.cat(blobs)
labels = torch.cat([torch.full((per_class,), i, dtype=torch.long)
                     for i in range(3)])

dataset = TensorDataset(points, labels)
torch.manual_seed(2)
loader = DataLoader(dataset, batch_size=32, shuffle=True)

torch.manual_seed(1)
model = nn.Sequential(
    nn.Linear(2, 16),
    nn.ReLU(),
    nn.Linear(16, 3),
)
loss_fn = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.05)

for epoch in range(30):
    for batch_points, batch_labels in loader:
        scores = model(batch_points)
        loss = loss_fn(scores, batch_labels)
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

model.eval()
with torch.no_grad():
    predictions = model(points).argmax(dim=1)
    correct = int((predictions == labels).sum())
    accuracy = correct / labels.shape[0] * 100

print("Points:", points.shape[0])
print("Correct:", correct, "of", labels.shape[0])
print(f"Final accuracy: {accuracy:.0f}%")

Key points

  • Multi-class: one correct class per row, chosen from three or more
  • Use nn.Sequential to stack Linear, ReLU, and a final Linear
  • The last layer gives one output per class
  • CrossEntropyLoss takes the scores and the correct class numbers
  • Use a DataLoader to feed the model shuffled batches
  • Three scores per row carry the answer, and argmax reads the winner

In this example, three blobs of 60 points sit around three centres. The labels are class numbers 0, 1, and 2, in int64. A TensorDataset pairs the points with the labels, and a DataLoader serves batches of 32 with shuffling. A seed is set before the model is built. The model is an MLP with a hidden layer of 16 and three outputs. CrossEntropyLoss and Adam train it for 30 epochs. At the end, argmax reads one prediction per point, and all 180 predictions are right.

Try it Yourself

Edit the code, then press Run.

Running is simulated ยท Python Playground

Exercise

What does the final Linear layer of a three-class MLP output for each row?