Thuta Learning
IntermediateAIintermediate

Building an Image Classifier

What you'll walk away with

  • Explain the core ideas behind Building an Image Classifier
  • Run the sample code and verify its output
  • Apply the technique correctly to the Tutorial Platform and production scenarios

Build the mental model

An image classifier is simply a feature extractor bolted onto a decision head. Each Conv2d layer detects local patterns (edges, textures, shape fragments); ReLU adds non-linearity; MaxPool shrinks the spatial dimensions while keeping the strongest activations. Stacking blocks lets the network build progressively more abstract features — from low-level edges to high-level object parts. At the end, Flatten turns the spatial feature map into a vector, and a Linear layer (the classifier head) outputs one score per class. This beats a plain fully-connected network on images because convolution shares weights across the whole spatial extent — the same small filter slides everywhere, so you don't need a separate weight for every pixel position.

The training loop itself is the same forward → loss → backward → optimizer.step() pattern from the PyTorch fundamentals course, but here the input is an image tensor and cross-entropy loss implicitly converts the raw class-score logits into probabilities before comparing them against the true integer labels. Training repeatedly on one fixed batch (deliberately overfitting it) is a useful sanity check for a new architecture or training loop: if the loss refuses to go down even on a single batch, something in the model or loop is broken, and you want to know that before scaling up to a real dataset.

Connect it to a real scenario

Suppose the Tutorial Platform is prototyping a feature that auto-tags instructor-uploaded course thumbnails by topic category (Programming, Design, Math, and so on). Before touching any real thumbnails, you'd build exactly this kind of small CNN and verify the training loop works correctly on synthetic data first — confirming the architecture and loop are bug-free before ever pointing it at the real thumbnail dataset.

Try the working example

python
import torch
import torch.nn as nn
import torch.optim as optim

torch.manual_seed(0)

class SimpleCNN(nn.Module):
    def __init__(self, num_classes=10):
        super().__init__()
        self.features = nn.Sequential(
            nn.Conv2d(3, 16, kernel_size=3, padding=1),
            nn.ReLU(),
            nn.MaxPool2d(2),  # 32x32 -> 16x16
            nn.Conv2d(16, 32, kernel_size=3, padding=1),
            nn.ReLU(),
            nn.MaxPool2d(2),  # 16x16 -> 8x8
        )
        self.classifier = nn.Sequential(
            nn.Flatten(),
            nn.Linear(32 * 8 * 8, num_classes),
        )

    def forward(self, x):
        x = self.features(x)
        return self.classifier(x)

model = SimpleCNN(num_classes=10)
optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.9)
criterion = nn.CrossEntropyLoss()

# Fake batch: 8 RGB images, 32x32, with random integer labels 0-9
images = torch.randn(8, 3, 32, 32)
labels = torch.randint(0, 10, (8,))

for step in range(5):
    optimizer.zero_grad()
    outputs = model(images)
    loss = criterion(outputs, labels)
    loss.backward()
    optimizer.step()
    print(f"step {step}: loss = {loss.item():.4f}")
You should see
Prints five lines in the form 'step 0: loss = X.XXXX' through 'step 4: loss = X.XXXX'. Because the model trains repeatedly on the exact same fixed batch, the loss should trend downward across the five steps overall (it may not be strictly monotonic step-to-step), starting near ln(10) ≈ 2.30 — the expected cross-entropy loss for a freshly initialized 10-way classifier making essentially random guesses.

5-minute try-it

Extend the training loop to run for 50 steps instead of 5, then after the loop, take the final step's output logits, apply argmax(dim=1) to get predicted labels, and add code that computes and prints accuracy against the true labels.

One important caution

Forgetting to hand-compute the flattened feature size (it depends on input resolution and how many MaxPool layers halve it) leads to a shape mismatch RuntimeError when constructing the Linear layer's in_features.

Skipping optimizer.zero_grad() at the start of each loop iteration causes gradients to accumulate across steps, making the loss behave erratically instead of decreasing.

PyTorch Tutorials — Training a Classifier (CIFAR10)Computer Vision

Easy traps

  • Forgetting to hand-compute the flattened feature size (it depends on input resolution and how many MaxPool layers halve it) leads to a shape mismatch RuntimeError when constructing the Linear layer's in_features.
  • Skipping optimizer.zero_grad() at the start of each loop iteration causes gradients to accumulate across steps, making the loss behave erratically instead of decreasing.
  • Validate sample code in a local or test environment before applying it to a production system.

Exercise

Extend the training loop to run for 50 steps instead of 5, then after the loop, take the final step's output logits, apply argmax(dim=1) to get predicted labels, and add code that computes and prints accuracy against the true labels.

You'll know it worked when: Prints five lines in the form 'step 0: loss = X.XXXX' through 'step 4: loss = X.XXXX'. Because the model trains repeatedly on the exact same fixed batch, the loss should trend downward across the five steps overall (it may not be strictly monotonic step-to-step), starting near ln(10) ≈ 2.30 — the expected cross-entropy loss for a freshly initialized 10-way classifier making essentially random guesses.

Building an Image Classifier | Thuta Learning