Een CNN bouwen en trainen op CIFAR-10
Cursisten stapelen Conv2d-ReLU-MaxPool-blokken, flattenen de featuremap, voegen een lineaire classifier toe en trainen op CIFAR-10 met data-augmentatie.
Een CNN bouwen en trainen op CIFAR-10 is een gratis Machine Learning Academy-les op CoddyKit. Dit is les 3 van 4. Je kunt de volledige les hieronder gratis lezen en daarna in de browser praktisch oefenen met een ingebouwde code-editor en een AI-begeleider die 24/7 beschikbaar is. Deze les maakt deel uit van het leertraject Machine Learning Academy. Je voortgang wordt gesynchroniseerd op het web en in de CoddyKit-app. De cursus Machine Learning Academy bevat in totaal 4 lessen.
CIFAR-10: de standaardgegevensverzameling
CIFAR-10 is een klassieke benchmark voor beeldclassificatie met 60.000 kleurenafbeeldingen (32x32 pixels, RGB) in 10 klassen: vliegtuig, auto, vogel, kat, hert, hond, kikker, paard, schip en vrachtwagen. Er zijn 50.000 trainingsafbeeldingen en 10.000 toetsafbeeldingen. De verzameling is klein genoeg om in enkele uren op een laptop te trainen, maar complex genoeg om eenvoudige modellen te laten falen, waardoor deze ideaal is om CNN-ontwerp te leren. PyTorch maakt de verzameling direct beschikbaar via torchvision.datasets.CIFAR10.
import torchvision
import torchvision.transforms as transforms
transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize(
mean=(0.4914, 0.4822, 0.4465),
std=(0.2023, 0.1994, 0.2010)
)
])
train_set = torchvision.datasets.CIFAR10(
root='./data', train=True,
download=True, transform=transform
)
print('Training images:', len(train_set)) # 50000
print('Image shape:', train_set[0][0].shape) # (3, 32, 32)Gegevens laden met DataLoader
Wikkel de gegevensverzameling na het definiëren ervan in een DataLoader die het opdelen in batches, schudden en parallel laden afhandelt. Voor CIFAR-10 is een batchgrootte van 64 of 128 gebruikelijk. Stel shuffle=True in voor trainingsgegevens om de volgorde in elke epoch willekeurig te maken, en shuffle=False voor de toetsset (de volgorde is niet belangrijk voor de evaluatie). Met num_workers=2 worden gegevens parallel met het trainen geladen, zodat de tijd waarin de GPU niets doet tijdens het ophalen van gegevens afneemt.
from torch.utils.data import DataLoader
train_loader = DataLoader(
train_set,
batch_size=128,
shuffle=True,
num_workers=2,
pin_memory=True # faster GPU transfer
)
# Peek at one batch
X_batch, y_batch = next(iter(train_loader))
print('Batch images:', X_batch.shape) # (128, 3, 32, 32)
print('Batch labels:', y_batch.shape) # (128,)De CNN-architectuur ontwerpen
Voor CIFAR-10 werkt een CNN met 3 blokken goed: elk blok heeft twee Conv-BN-ReLU-lagen, gevolgd door max pooling. Daarbij verdubbelt het aantal kanalen (32 -> 64 -> 128) terwijl de ruimtelijke omvang halveert (32 -> 16 -> 8 -> 4). Na de convolutieblokken voegt globale gemiddelde pooling de ruimtelijke dimensies samen en brengt een lineaire laag de uitvoer in kaart naar 10 klassescores. Dit ontwerp heeft ongeveer 250K parameters: klein genoeg om snel te trainen en toch een nauwkeurigheid van meer dan 80% te behalen zonder gegevensaugmentatie.
import torch.nn as nn
class CIFAR10Net(nn.Module):
def __init__(self):
super().__init__()
self.features = nn.Sequential(
nn.Conv2d(3, 32, 3, padding=1), nn.BatchNorm2d(32), nn.ReLU(),
nn.Conv2d(32, 32, 3, padding=1), nn.BatchNorm2d(32), nn.ReLU(),
nn.MaxPool2d(2), # 32->16
nn.Conv2d(32, 64, 3, padding=1), nn.BatchNorm2d(64), nn.ReLU(),
nn.Conv2d(64, 64, 3, padding=1), nn.BatchNorm2d(64), nn.ReLU(),
nn.MaxPool2d(2), # 16->8
nn.Conv2d(64, 128, 3, padding=1), nn.BatchNorm2d(128), nn.ReLU(),
nn.MaxPool2d(2), # 8->4
)
self.classifier = nn.Sequential(
nn.AdaptiveAvgPool2d((1, 1)),
nn.Flatten(),
nn.Linear(128, 10)
)
def forward(self, x):
return self.classifier(self.features(x))Trainingscomponenten instellen
Configureer voor CIFAR-10-classificatie het volgende: CrossEntropyLoss als criterium (onbewerkte logits voor 10 klassen), Adam of SGD met momentum als optimalisator en een cosinusvormige annealing- of stapsgewijze LR-planner om de leersnelheid tijdens het trainen te verlagen. Verplaats het model met .to(device) naar de GPU. Print het totale aantal parameters als plausibiliteitscontrole voordat je de kostbare trainingsrun start.
import torch
import torch.nn as nn
import torch.optim as optim
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model = CIFAR10Net().to(device)
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(
model.parameters(),
lr=0.1,
momentum=0.9,
weight_decay=5e-4
)
scheduler = optim.lr_scheduler.CosineAnnealingLR(
optimizer, T_max=50
)
total_params = sum(p.numel() for p in model.parameters())
print(f'Parameters: {total_params:,}') # ~250,000De functie voor een trainingsepoch
Door één trainingsepoch in een functie onder te brengen, blijft de code herbruikbaar en overzichtelijk. De functie doorloopt alle batches, voert de update in 4 stappen uit, telt het verlies en de correcte voorspellingen op en retourneert het gemiddelde verlies en de nauwkeurigheid. Zowel X_batch als y_batch binnen de lus naar het apparaat verplaatsen is het juiste patroon. Vooraf laden met pin_memory=True in de DataLoader versnelt deze overdracht.
import torch
def train_epoch(model, loader, criterion, optimizer, device):
model.train()
total_loss, correct, total = 0.0, 0, 0
for X, y in loader:
X, y = X.to(device), y.to(device)
optimizer.zero_grad()
logits = model(X)
loss = criterion(logits, y)
loss.backward()
optimizer.step()
total_loss += loss.item() * X.size(0)
correct += (logits.argmax(1) == y).sum().item()
total += X.size(0)
return total_loss / total, correct / totalDe functie voor een validatie-epoch
De validatiefunctie is identiek aan de trainingsfunctie, met deze uitzonderingen: model.eval() schakelt de stochastiek van Dropout en BatchNorm uit; torch.no_grad() schakelt het bijhouden van gradiënten uit voor meer snelheid; en er is geen stap van de optimalisator. De geretourneerde validatienauwkeurigheid en het validatieverlies worden gebruikt om de generalisatieprestaties te volgen, overfitting te detecteren en de leersnelheid aan te sturen via ReduceLROnPlateau.
import torch
def eval_epoch(model, loader, criterion, device):
model.eval()
total_loss, correct, total = 0.0, 0, 0
with torch.no_grad():
for X, y in loader:
X, y = X.to(device), y.to(device)
logits = model(X)
loss = criterion(logits, y)
total_loss += loss.item() * X.size(0)
correct += (logits.argmax(1) == y).sum().item()
total += X.size(0)
return total_loss / total, correct / totalDe volledige trainingslus
Wanneer de functies voor trainings- en validatie-epochs zijn gedefinieerd, voert de buitenste lus num_epochs iteraties uit. Verhoog na elke epoch de stap van de LR-planner en sla het model op wanneer de validatienauwkeurigheid verbetert. Door in elke epoch meetwaarden te printen, houd je zicht op het verloop: bij een goed afgestemde CNN hoort de trainingsnauwkeurigheid te stijgen van ongeveer 30% in de eerste epoch naar meer dan 90% in epoch 50. De validatienauwkeurigheid ligt doorgaans 5 tot 10 procentpunten achter op de training.
num_epochs = 50
best_val_acc = 0.0
for epoch in range(num_epochs):
tr_loss, tr_acc = train_epoch(
model, train_loader, criterion, optimizer, device)
val_loss, val_acc = eval_epoch(
model, val_loader, criterion, device)
scheduler.step()
print(f'Epoch {epoch+1:03d}: '
f'tr_loss={tr_loss:.3f} tr_acc={tr_acc:.3f} '
f'val_loss={val_loss:.3f} val_acc={val_acc:.3f}')
if val_acc > best_val_acc:
best_val_acc = val_acc
torch.save(model.state_dict(), 'best_cifar10.pt')Gegevensaugmentatie voor betere nauwkeurigheid
Gegevensaugmentatie past willekeurige transformaties toe op trainingsafbeeldingen, waardoor de gegevensverzameling kunstmatig wordt uitgebreid en het model robuuster wordt. Voor CIFAR-10 zijn een willekeurige horizontale spiegeling, een willekeurige uitsnede (met opvulling) en kleurvariatie gebruikelijk. Augmentatie verbetert de nauwkeurigheid doorgaans met 3 tot 5 procentpunten. Pas augmentatie alleen toe op de trainingstransformatie; de toets transformatie gebruikt voor deterministische evaluatie alleen normalisatie.
import torchvision.transforms as transforms
train_transform = transforms.Compose([
transforms.RandomCrop(32, padding=4), # shift by 4px
transforms.RandomHorizontalFlip(), # mirror 50%
transforms.ColorJitter(
brightness=0.2, contrast=0.2,
saturation=0.2, hue=0.1
),
transforms.ToTensor(),
transforms.Normalize(
(0.4914, 0.4822, 0.4465),
(0.2023, 0.1994, 0.2010)
)
])
test_transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize(
(0.4914, 0.4822, 0.4465),
(0.2023, 0.1994, 0.2010)
)
])Trainingscurven interpreteren
Leren lezen van trainingscurves is essentieel voor de ontwikkeling van CNN's. Een convergerend model laat zien dat zowel het trainingsverlies als het validatieverlies gelijktijdig afneemt. Overfitting blijkt uit trainingsverlies dat bijna nul is, terwijl het validatieverlies afvlakt of stijgt. Underfitting blijkt uit twee verliezen die hoog en vlak blijven. Voor CIFAR-10 hoort een gezonde run van 50 epochs het volgende te laten zien: in epoch 1 ongeveer 35% nauwkeurigheid, in epoch 10 ongeveer 70% en in epoch 50 ongeveer 85-90% validatienauwkeurigheid met de beschreven architectuur en gegevensaugmentatie.
# Typical CIFAR-10 accuracy milestones
milestones = {
'Epoch 1': 'val_acc ~35% (random = 10%)',
'Epoch 5': 'val_acc ~60% (basic patterns learned)',
'Epoch 10': 'val_acc ~70% (edges, textures)',
'Epoch 20': 'val_acc ~78% (object parts)',
'Epoch 50': 'val_acc ~85% (with augmentation)',
'With ResNet18': 'val_acc ~93%',
'State of art': 'val_acc ~99% (huge ensembles)'
}
for epoch, note in milestones.items():
print(f'{epoch}: {note}')Nauwkeurigheidsanalyse per klasse
De algehele nauwkeurigheid verbergt verschillen in prestaties per klasse. Sommige CIFAR-10-klassen zijn moeilijker van elkaar te onderscheiden — 'cat' versus 'dog' en 'automobile' versus 'truck' zijn veelvoorkomende verwarringsparen. Het berekenen van nauwkeurigheid per klasse of het tekenen van de verwarringsmatrix laat zien met welke klassen het model moeite heeft. Dat helpt bij het gericht verzamelen van gegevens of het kiezen van augmentatiestrategieën. Gebruik sklearn.metrics.confusion_matrix voor de verzamelde voorspellingen en labels.
import torch
classes = ['airplane', 'auto', 'bird', 'cat', 'deer',
'dog', 'frog', 'horse', 'ship', 'truck']
# Collect all predictions
all_preds, all_labels = [], []
model.eval()
with torch.no_grad():
for X, y in test_loader:
X = X.to(device)
preds = model(X).argmax(1).cpu()
all_preds.extend(preds.tolist())
all_labels.extend(y.tolist())
# Per-class accuracy
for i, cls in enumerate(classes):
mask = [l == i for l in all_labels]
correct = sum(p == l for p, l in zip(all_preds, all_labels) if l == i)
total = sum(mask)
print(f'{cls}: {correct}/{total} = {correct/total:.1%}')CutMix- en Mixup-augmentaties
Naast standaardaugmentatie kunnen geavanceerde technieken de prestaties van CNN's verder verbeteren. Mixup interpoleert lineair tussen twee trainingsafbeeldingen en hun labels: het model moet een combinatie van beide klassen voorspellen. CutMix plakt een rechthoekig fragment uit de ene afbeelding op een andere en kent labels toe in verhouding tot het oppervlak. Beide werken als sterke regularisatoren en verminderen overfitting. Ze zijn standaard in geavanceerde CIFAR-10-trainingsruns en voegen 1-3% nauwkeurigheid toe bovenop alleen een willekeurige uitsnede en spiegeling.
import torch
def mixup_batch(X, y, alpha=0.2, num_classes=10):
lam = torch.distributions.Beta(alpha, alpha).sample()
idx = torch.randperm(X.size(0))
X_mix = lam * X + (1 - lam) * X[idx]
# Soft labels: blend of one-hot vectors
y_onehot = torch.zeros(X.size(0), num_classes)
y_onehot.scatter_(1, y.unsqueeze(1), 1)
y_onehot2 = y_onehot[idx]
y_mix = lam * y_onehot + (1 - lam) * y_onehot2
return X_mix, y_mix
# Use with soft-label cross entropy
# loss = -(y_mix * F.log_softmax(logits, dim=1)).sum(dim=1).mean()Korte controle
Test uw begrip van de concepten uit deze les over Machine Learning with Python.
Samenvatting van de les
In deze les hebt u geleerd dat CIFAR-10 de standaardbenchmark voor afbeeldingen met 10 klassen is, met 50K trainingsafbeeldingen en 10K testafbeeldingen van 32x32 RGB-pixels, dat een CNN met 3 blokken en BatchNorm na 50 epochs ongeveer 85% nauwkeurigheid behaalt met standaardaugmentatie, en dat gegevensaugmentatie (willekeurige uitsnede, horizontale spiegeling en kleurvariatie) essentieel is om het verschil tussen trainings- en testnauwkeurigheid te verkleinen. Hierna bekijken we transformaties voor gegevensaugmentatie in detail, zodat je robuustere modellen kunt bouwen.
Leer Python met een AI-tutor — gratis
Schrijf echte code en voer die uit in je browser, krijg direct hulp van een AI-tutor die 24/7 beschikbaar is en ga verder waar je gebleven bent op het web of in de app.
- Cursussen
- 30
- Lessen
- 120
Veelgestelde vragen
Is de les “Een CNN bouwen en trainen op CIFAR-10” gratis?
Ja — de volledige tekst van “Een CNN bouwen en trainen op CIFAR-10” kun je hier gratis op het web lezen. Als je interactief wilt oefenen met een ingebouwde code-editor en een AI-begeleider die 24/7 beschikbaar is, en de rest van de cursus Machine Learning Academy wilt ontgrendelen, kun je upgraden naar CoddyKit PRO. De cursus Machine Learning Academy bevat in totaal 4 lessen.
Wat leer ik in “Een CNN bouwen en trainen op CIFAR-10”?
Cursisten stapelen Conv2d-ReLU-MaxPool-blokken, flattenen de featuremap, voegen een lineaire classifier toe en trainen op CIFAR-10 met data-augmentatie. Je oefent met Machine Learning Academy door code rechtstreeks in de browser uit te voeren. Een AI-begeleider die 24/7 beschikbaar is beantwoordt je vragen terwijl je de les doorwerkt.
Heb ik ervaring nodig om met Machine Learning Academy te beginnen?
Ervaring vooraf is niet nodig. Machine Learning Academy op CoddyKit is opgebouwd voor beginners tot gevorderden, zodat je hier of bij het begin kunt starten en in je eigen tempo kunt leren. Dit is les 3 van 4.
Hoe lang duurt de les “Een CNN bouwen en trainen op CIFAR-10”?
De meeste lessen van CoddyKit duren ongeveer 5–10 minuten. Elke les is kort en interactief, zodat je gestaag vooruitgaat en op het web en in de app precies verdergaat waar je was gebleven.
Kan ik code schrijven en uitvoeren in deze les over Machine Learning Academy?
Ja. Elke les over Machine Learning Academy bevat een ingebouwde code-editor, zodat je rechtstreeks in je browser echte code kunt schrijven en uitvoeren en direct feedback van AI krijgt — lokale installatie is niet nodig.
Alle lessen in deze cursus
- Convolutie en filters: randen en patronen detecteren
- Poolinglagen: ruimtelijke downsampling en invariantie
- Een CNN bouwen en trainen op CIFAR-10
- Data-augmentatie: transformaties voor robuustheid