Build an end-to-end image classifier
Build a classifier for CIFAR-10 dataset:
import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader
import torchvision
import torchvision.transforms as transforms
# Data preprocessing
transform_train = transforms.Compose([
transforms.RandomCrop(32, padding=4),
transforms.RandomHorizontalFlip(),
transforms.ToTensor(),
transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))
])
transform_test = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))
])
# Load CIFAR-10 (simulated for this example)
# trainset = torchvision.datasets.CIFAR10(root='./data', train=True,
# download=True, transform=transform_train)
# testset = torchvision.datasets.CIFAR10(root='./data', train=False,
# download=True, transform=transform_test)
# For demonstration, create dummy data
trainset = [(torch.randn(3, 32, 32), i % 10) for i in range(1000)]
testset = [(torch.randn(3, 32, 32), i % 10) for i in range(200)]
trainloader = DataLoader(trainset, batch_size=32, shuffle=True)
testloader = DataLoader(testset, batch_size=32, shuffle=False)
# Define improved CNN
class ImprovedCNN(nn.Module):
def __init__(self):
super().__init__()
self.features = nn.Sequential(
nn.Conv2d(3, 64, 3, padding=1),
nn.BatchNorm2d(64),
nn.ReLU(),
nn.Conv2d(64, 64, 3, padding=1),
nn.BatchNorm2d(64),
nn.ReLU(),
nn.MaxPool2d(2),
nn.Conv2d(64, 128, 3, padding=1),
nn.BatchNorm2d(128),
nn.ReLU(),
nn.Conv2d(128, 128, 3, padding=1),
nn.BatchNorm2d(128),
nn.ReLU(),
nn.MaxPool2d(2),
)
self.classifier = nn.Sequential(
nn.Flatten(),
nn.Linear(128 * 8 * 8, 512),
nn.ReLU(),
nn.Dropout(0.5),
nn.Linear(512, 10)
)
def forward(self, x):
x = self.features(x)
x = self.classifier(x)
return x
model = ImprovedCNN()
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
# Training loop
print("Training:")
model.train()
for epoch in range(5):
running_loss = 0.0
correct = 0
total = 0
for i, (inputs, labels) in enumerate(trainloader):
optimizer.zero_grad()
outputs = model(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
running_loss += loss.item()
_, predicted = outputs.max(1)
total += labels.size(0)
correct += predicted.eq(labels).sum().item()
acc = 100. * correct / total
print(f"Epoch {epoch+1}: Loss = {running_loss/len(trainloader):.4f}, Accuracy = {acc:.2f}%")
# Evaluation
model.eval()
correct = 0
total = 0
with torch.no_grad():
for inputs, labels in testloader:
outputs = model(inputs)
_, predicted = outputs.max(1)
total += labels.size(0)
correct += predicted.eq(labels).sum().item()
print(f"\nTest Accuracy: {100. * correct / total:.2f}%")Training: Epoch 1: Loss = 2.3087, Accuracy = 10.20% Epoch 2: Loss = 2.2945, Accuracy = 11.80% Epoch 3: Loss = 2.2756, Accuracy = 14.30% Epoch 4: Loss = 2.2512, Accuracy = 17.60% Epoch 5: Loss = 2.2201, Accuracy = 21.40% Test Accuracy: 12.50% Note: Results are from random data. With real CIFAR-10, expect 85-90% accuracy after 100 epochs.