iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

CNN

A PyTorch CNN is a nn.Module with Conv2d / BatchNorm2d / MaxPool2d layers, trained with a standard loop. CIFAR-10 reaches 90%+ accuracy with ~30 lines of model code.

CIFAR-10 CNN + training loop

EXAMPLE
import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.utils.data import DataLoader
from torchvision import datasets, transforms

device = 'cuda' if torch.cuda.is_available() else 'cpu'

# 1) Data + augmentation
mean, std = (0.4914, 0.4822, 0.4465), (0.2470, 0.2435, 0.2616)
train_tf = transforms.Compose([
    transforms.RandomCrop(32, padding=4),
    transforms.RandomHorizontalFlip(),
    transforms.ToTensor(),
    transforms.Normalize(mean, std),
])
test_tf = transforms.Compose([transforms.ToTensor(), transforms.Normalize(mean, std)])

train_ds = datasets.CIFAR10('./data', train=True,  download=True, transform=train_tf)
test_ds  = datasets.CIFAR10('./data', train=False, download=True, transform=test_tf)

train_dl = DataLoader(train_ds, batch_size=128, shuffle=True,  num_workers=4, pin_memory=True)
test_dl  = DataLoader(test_ds,  batch_size=256, shuffle=False, num_workers=4, pin_memory=True)

# 2) Model — small VGG-style
class ConvBlock(nn.Module):
    def __init__(self, in_c, out_c):
        super().__init__()
        self.c1 = nn.Conv2d(in_c, out_c, 3, padding=1, bias=False)
        self.b1 = nn.BatchNorm2d(out_c)
        self.c2 = nn.Conv2d(out_c, out_c, 3, padding=1, bias=False)
        self.b2 = nn.BatchNorm2d(out_c)
    def forward(self, x):
        x = F.relu(self.b1(self.c1(x)))
        x = F.relu(self.b2(self.c2(x)))
        return F.max_pool2d(x, 2)

class SmallVGG(nn.Module):
    def __init__(self, n_classes=10):
        super().__init__()
        self.block1 = ConvBlock(3,   32)
        self.block2 = ConvBlock(32,  64)
        self.block3 = ConvBlock(64, 128)
        self.head = nn.Sequential(
            nn.Flatten(),
            nn.Linear(128 * 4 * 4, 256), nn.ReLU(), nn.Dropout(0.5),
            nn.Linear(256, n_classes),
        )
    def forward(self, x):
        return self.head(self.block3(self.block2(self.block1(x))))

model = SmallVGG().to(device)
opt   = torch.optim.AdamW(model.parameters(), lr=3e-4, weight_decay=1e-4)
sched = torch.optim.lr_scheduler.CosineAnnealingLR(opt, T_max=30)
loss_fn = nn.CrossEntropyLoss()
scaler  = torch.amp.GradScaler('cuda')

# 3) Train
best = 0.0
for epoch in range(1, 31):
    model.train()
    for x, y in train_dl:
        x, y = x.to(device, non_blocking=True), y.to(device, non_blocking=True)
        opt.zero_grad(set_to_none=True)
        with torch.amp.autocast('cuda', dtype=torch.float16):
            loss = loss_fn(model(x), y)
        scaler.scale(loss).backward()
        scaler.step(opt)
        scaler.update()
    sched.step()

    # 4) Eval
    model.eval()
    correct, total = 0, 0
    with torch.inference_mode():
        for x, y in test_dl:
            x, y = x.to(device), y.to(device)
            correct += (model(x).argmax(1) == y).sum().item()
            total   += y.size(0)
    acc = correct / total
    print(f'ep {epoch}  test_acc={acc:.4f}')
    if acc > best:
        best = acc
        torch.save({'model': model.state_dict(), 'acc': acc}, 'best.pt')

# 5) Transfer learning — alternative starting point
from torchvision.models import resnet18, ResNet18_Weights
base = resnet18(weights=ResNet18_Weights.DEFAULT)
base.fc = nn.Linear(base.fc.in_features, 10)
# Optionally freeze backbone:
# for p in base.parameters(): p.requires_grad = False
# for p in base.fc.parameters(): p.requires_grad = True

# 6) Predict
model.eval()
with torch.inference_mode():
    probs = F.softmax(model(x_one.unsqueeze(0).to(device)), dim=1)

Why it matters

set_to_none=True on zero_grad + AMP autocast + cosine LR schedule = a CIFAR-10 baseline that trains fast on a laptop GPU and hits 90%. Defaults compound.

Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.

Example

Example
import torch.nn as nn
cnn = nn.Sequential(
    nn.Conv2d(1, 32, 3, padding=1), nn.ReLU(), nn.MaxPool2d(2),
    nn.Conv2d(32, 64, 3, padding=1), nn.ReLU(), nn.AdaptiveAvgPool2d(1),
    nn.Flatten(), nn.Linear(64, 10),
)
Try it Yourself »

Discussion

Loading…