Computer Vision met PyTorch in 2026: CNNs, Transfer Learning en Sollicitatievragen
Computer vision met PyTorch: bouw CNNs vanaf nul, pas transfer learning toe met voorgetrainde modellen en bereid je voor op technische sollicitatiegesprekken.

Computer vision met PyTorch is in 2026 de dominante aanpak geworden voor beeldclassificatie, objectdetectie en visuele herkenningstaken. Deze tutorial behandelt het bouwen van CNNs vanaf nul, het toepassen van transfer learning met voorgetrainde modellen en de voorbereiding op technische sollicitatievragen.
PyTorch 2.4 introduceert torch.compile() standaard voor CNN-operaties, wat 30-50% snelheidsverbeteringen oplevert op moderne GPUs zonder codewijzigingen. Alle voorbeelden in dit artikel zijn compatibel met PyTorch 2.4+.
Convolutionele Neurale Netwerken voor Beeldclassificatie Begrijpen
Convolutionele Neurale Netwerken extraheren hiërarchische kenmerken uit afbeeldingen door middel van leerbare filters. In tegenstelling tot volledig verbonden netwerken behouden CNNs de ruimtelijke relaties tussen pixels, waardoor ze ideaal zijn voor visuele taken. De architectuur bestaat uit convolutielagen die randen en patronen detecteren, pooling-lagen die de dimensionaliteit verminderen en volledig verbonden lagen die de classificatie uitvoeren.
Een convolutie-operatie schuift een kleine filter (typisch 3x3 of 5x5) over de invoerafbeelding en berekent inproducten op elke positie. Dit produceert feature maps die specifieke patronen zoals randen, texturen of vormen benadrukken. Diepere lagen combineren deze laag-niveau kenmerken tot complexe representaties—gezichten, objecten of scènes.
# cnn_architecture.py
import torch
import torch.nn as nn
class SimpleCNN(nn.Module):
"""Basic CNN for CIFAR-10 classification (32x32 RGB images, 10 classes)"""
def __init__(self, num_classes: int = 10):
super().__init__()
# First conv block: 3 input channels (RGB) -> 32 feature maps
self.conv1 = nn.Sequential(
nn.Conv2d(3, 32, kernel_size=3, padding=1), # Output: 32x32x32
nn.BatchNorm2d(32), # Normalize activations for stable training
nn.ReLU(inplace=True),
nn.MaxPool2d(2, 2) # Output: 16x16x32
)
# Second conv block: increase depth for richer features
self.conv2 = nn.Sequential(
nn.Conv2d(32, 64, kernel_size=3, padding=1), # Output: 16x16x64
nn.BatchNorm2d(64),
nn.ReLU(inplace=True),
nn.MaxPool2d(2, 2) # Output: 8x8x64
)
# Third conv block: capture high-level patterns
self.conv3 = nn.Sequential(
nn.Conv2d(64, 128, kernel_size=3, padding=1), # Output: 8x8x128
nn.BatchNorm2d(128),
nn.ReLU(inplace=True),
nn.MaxPool2d(2, 2) # Output: 4x4x128
)
# Classifier head
self.classifier = nn.Sequential(
nn.Flatten(),
nn.Linear(128 * 4 * 4, 256),
nn.ReLU(inplace=True),
nn.Dropout(0.5), # Prevent overfitting
nn.Linear(256, num_classes)
)
def forward(self, x: torch.Tensor) -> torch.Tensor:
x = self.conv1(x)
x = self.conv2(x)
x = self.conv3(x)
return self.classifier(x)Deze architectuur verhoogt progressief het aantal filters (32 → 64 → 128) terwijl de ruimtelijke dimensies worden verminderd door pooling. BatchNorm stabiliseert de training door laaguitvoer te normaliseren, terwijl Dropout voorkomt dat de classificator trainingsvoorbeelden uit het hoofd leert.
Een CNN Trainen met PyTorch DataLoaders
Efficiënt laden van data is cruciaal voor GPU-benutting tijdens training. PyTorch's DataLoader verzorgt automatisch batching, shuffling en parallel laden van data. Goede data-augmentatie—willekeurige uitsnedes, spiegelingen en kleurvariaties—verbetert de generalisatie op ongeziene afbeeldingen aanzienlijk.
# train_cnn.py
import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader
from torchvision import datasets, transforms
# Data augmentation for training (reduces overfitting)
train_transform = transforms.Compose([
transforms.RandomHorizontalFlip(p=0.5),
transforms.RandomCrop(32, padding=4), # Random crop with padding
transforms.ColorJitter(brightness=0.2, contrast=0.2),
transforms.ToTensor(),
transforms.Normalize((0.4914, 0.4822, 0.4465), # CIFAR-10 mean
(0.2470, 0.2435, 0.2616)) # CIFAR-10 std
])
# No augmentation for validation (deterministic evaluation)
val_transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.4914, 0.4822, 0.4465),
(0.2470, 0.2435, 0.2616))
])
def train_model(model: nn.Module, epochs: int = 20) -> dict:
"""Train CNN with standard best practices"""
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model = model.to(device)
# Load CIFAR-10 dataset
train_data = datasets.CIFAR10(root="./data", train=True,
download=True, transform=train_transform)
val_data = datasets.CIFAR10(root="./data", train=False,
transform=val_transform)
# DataLoaders with num_workers for parallel loading
train_loader = DataLoader(train_data, batch_size=128, shuffle=True,
num_workers=4, pin_memory=True)
val_loader = DataLoader(val_data, batch_size=256, shuffle=False,
num_workers=4, pin_memory=True)
criterion = nn.CrossEntropyLoss()
optimizer = optim.AdamW(model.parameters(), lr=1e-3, weight_decay=1e-4)
scheduler = optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max=epochs)
best_acc = 0.0
for epoch in range(epochs):
model.train()
for images, labels in train_loader:
images, labels = images.to(device), labels.to(device)
optimizer.zero_grad()
outputs = model(images)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
scheduler.step()
# Validation
model.eval()
correct, total = 0, 0
with torch.no_grad():
for images, labels in val_loader:
images, labels = images.to(device), labels.to(device)
outputs = model(images)
_, predicted = outputs.max(1)
total += labels.size(0)
correct += predicted.eq(labels).sum().item()
acc = 100. * correct / total
best_acc = max(best_acc, acc)
print(f"Epoch {epoch+1}/{epochs} - Val Acc: {acc:.2f}%")
return {"best_accuracy": best_acc}Belangrijke trainingsoptimalisaties omvatten: pin_memory=True voor snellere CPU-naar-GPU-overdrachten, num_workers voor parallel laden van data, AdamW-optimizer met weight decay voor regularisatie en cosine annealing learning rate scheduling voor geleidelijke convergentie.
Transfer Learning met Voorgetrainde ResNet en EfficientNet
Transfer learning maakt gebruik van modellen die voorgetraind zijn op ImageNet (1,2 miljoen afbeeldingen, 1000 klassen) en past deze aan voor aangepaste datasets. Deze aanpak bereikt hogere nauwkeurigheid met minder trainingsdata en rekentijd. PyTorch's torchvision.models biedt state-of-the-art architecturen met voorgetrainde gewichten.
De standaardaanpak bevriest vroege convolutielagen (die universele kenmerken zoals randen detecteren) en verfijnt latere lagen plus een nieuwe classificatiekop voor de doeltaak.
# transfer_learning.py
import torch
import torch.nn as nn
from torchvision import models
from torchvision.models import ResNet50_Weights, EfficientNet_B0_Weights
def create_transfer_model(
model_name: str = "resnet50",
num_classes: int = 10,
freeze_backbone: bool = True
) -> nn.Module:
"""Create a pretrained model with custom classification head"""
if model_name == "resnet50":
# Load ResNet50 with ImageNet weights
model = models.resnet50(weights=ResNet50_Weights.IMAGENET1K_V2)
# Replace final fully connected layer
in_features = model.fc.in_features # 2048 for ResNet50
model.fc = nn.Sequential(
nn.Dropout(0.3),
nn.Linear(in_features, num_classes)
)
elif model_name == "efficientnet_b0":
# EfficientNet: better accuracy/compute tradeoff
model = models.efficientnet_b0(weights=EfficientNet_B0_Weights.IMAGENET1K_V1)
in_features = model.classifier[1].in_features # 1280 for B0
model.classifier = nn.Sequential(
nn.Dropout(0.2),
nn.Linear(in_features, num_classes)
)
if freeze_backbone:
# Freeze all layers except classifier
for name, param in model.named_parameters():
if "fc" not in name and "classifier" not in name:
param.requires_grad = False
return model
def count_trainable_params(model: nn.Module) -> int:
"""Count parameters that will be updated during training"""
return sum(p.numel() for p in model.parameters() if p.requires_grad)
# Example usage
model = create_transfer_model("resnet50", num_classes=5, freeze_backbone=True)
print(f"Trainable parameters: {count_trainable_params(model):,}")
# Output: ~10,245 (only classifier) vs ~25 million (full ResNet50)Het bevriezen van de backbone reduceert de trainbare parameters van 25 miljoen naar ongeveer 10.000, waardoor training op kleine datasets mogelijk is zonder overfitting. Voor grotere datasets (10.000+ afbeeldingen) kunnen latere lagen geleidelijk worden ontdooid met differentiële learning rates—lagere rates voor voorgetrainde lagen, hogere rates voor de nieuwe classificator.
Klaar om je Data Science & ML gesprekken te halen?
Oefen met onze interactieve simulatoren, flashcards en technische tests.
Data-augmentatiestrategieën voor Computer Vision
Data-augmentatie breidt de trainingsset kunstmatig uit door transformaties toe te passen die de semantische inhoud behouden. Moderne augmentatie gaat verder dan eenvoudige spiegelingen en rotaties—technieken zoals MixUp en CutOut creëren synthetische trainingsvoorbeelden die de robuustheid van het model verbeteren.
# augmentation_strategies.py
import torch
import torchvision.transforms.v2 as T
from torchvision.transforms.v2 import functional as F
# Modern augmentation pipeline using torchvision v2 transforms
advanced_augmentation = T.Compose([
T.RandomResizedCrop(224, scale=(0.8, 1.0)), # Random crop and resize
T.RandomHorizontalFlip(p=0.5),
T.RandomVerticalFlip(p=0.1), # Less common but useful for some domains
T.RandomRotation(degrees=15),
T.ColorJitter(brightness=0.3, contrast=0.3, saturation=0.3, hue=0.1),
T.RandomAffine(degrees=0, translate=(0.1, 0.1)), # Small translations
T.GaussianBlur(kernel_size=3, sigma=(0.1, 2.0)),
T.ToImage(),
T.ToDtype(torch.float32, scale=True),
T.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
class CutOut:
"""Randomly mask out square regions of the image"""
def __init__(self, n_holes: int = 1, length: int = 16):
self.n_holes = n_holes
self.length = length
def __call__(self, img: torch.Tensor) -> torch.Tensor:
h, w = img.shape[1], img.shape[2]
mask = torch.ones_like(img)
for _ in range(self.n_holes):
y = torch.randint(0, h, (1,)).item()
x = torch.randint(0, w, (1,)).item()
y1 = max(0, y - self.length // 2)
y2 = min(h, y + self.length // 2)
x1 = max(0, x - self.length // 2)
x2 = min(w, x + self.length // 2)
mask[:, y1:y2, x1:x2] = 0
return img * mask
def mixup_data(
x: torch.Tensor,
y: torch.Tensor,
alpha: float = 0.4
) -> tuple[torch.Tensor, torch.Tensor, torch.Tensor, float]:
"""MixUp: blend two images and their labels"""
lam = torch.distributions.Beta(alpha, alpha).sample().item()
batch_size = x.size(0)
index = torch.randperm(batch_size)
mixed_x = lam * x + (1 - lam) * x[index]
y_a, y_b = y, y[index]
return mixed_x, y_a, y_b, lamCutOut dwingt het model om te vertrouwen op meerdere visuele aanwijzingen in plaats van een enkele discriminerende regio. MixUp creëert convexe combinaties van trainingsparen, wat resulteert in gladdere beslissingsgrenzen. Deze technieken verbeteren de nauwkeurigheid consistent met 1-3% op standaard benchmarks.
Sollicitatievragen over CNNs en Computer Vision
Technische sollicitatiegesprekken voor computer vision-functies testen zowel theoretisch begrip als praktische implementatievaardigheden. Voorbereiding moet vragen omvatten over architectuurontwerp, optimalisatie-uitdagingen en overwegingen voor deployment in de praktijk.
Interviewers vragen vaak naar berekeningen van het receptieve veld, het doel van batch normalisatie, waarom convoluties werken voor afbeeldingen en hoe overfitting in vision-modellen te diagnosticeren.
V: Wat is het receptieve veld en waarom is het belangrijk?
Het receptieve veld is het gebied van de invoerafbeelding dat een bepaalde feature map-locatie beïnvloedt. Diepere lagen hebben grotere receptieve velden, waardoor ze bredere context kunnen vastleggen. Voor een netwerk met n convolutielagen met 3x3 kernels groeit het receptieve veld als (2n + 1) × (2n + 1). Architectuurontwerp vereist het balanceren van de grootte van het receptieve veld tegen rekenkosten—gedilateerde convoluties vergroten receptieve velden zonder parameters te verhogen.
V: Waarom wordt batch normalisatie gebruikt in CNNs?
Batch normalisatie normaliseert laaginvoer naar nul gemiddelde en eenheidsvariantie, waarmee interne covariate shift wordt aangepakt. Voordelen omvatten: snellere convergentie (hogere learning rates worden stabiel), regularisatie-effect (vermindert behoefte aan dropout) en verbeterde gradiëntstroom (voorkomt verdwijnende gradiënten in diepe netwerken). Tijdens inferentie vervangen running statistics de batch-statistieken voor deterministische uitvoer.
V: Leg het verschil uit tussen same en valid padding.
Same padding voegt nullen toe rond de invoer om ruimtelijke dimensies te behouden na convolutie—een 32×32 invoer met een 3×3 kernel produceert een 32×32 uitvoer. Valid padding past geen padding toe en vermindert dimensies—dezelfde operatie produceert een 30×30 uitvoer. Same padding heeft de voorkeur in diepe netwerken om agressieve ruimtelijke reductie te voorkomen.
V: Hoe ga je om met klasse-onbalans bij beeldclassificatie?
Strategieën omvatten: gewogen cross-entropy loss (hogere gewichten voor minderheidsklassen), oversampling van minderheidsklassen tijdens training, data-augmentatie gericht op ondervertegenwoordigde klassen en focal loss die makkelijke voorbeelden naar beneden weegt. Bij ernstige onbalans (>100:1) is het raadzaam meerdere technieken te combineren en metrieken buiten nauwkeurigheid te overwegen—F1-score, precision-recall AUC of confusion matrix-analyse.
Voor verdere voorbereiding op deep learning-sollicitatiegesprekken kunnen de modules CNN & Beeldclassificatie en Deep Learning Fundamenten worden verkend.
PyTorch Vision-modellen Deployen met TorchScript
Productie-deployment vereist het converteren van PyTorch-modellen naar geoptimaliseerde formaten. TorchScript compileert modellen naar een draagbare representatie die zonder Python draait, waardoor deployment in C++-applicaties, mobiele apparaten of serverless omgevingen mogelijk wordt.
# deployment_export.py
import torch
from torchvision import models
from torchvision.models import ResNet18_Weights
def export_for_production(model: torch.nn.Module, save_path: str) -> None:
"""Export model to TorchScript for production deployment"""
model.eval() # Set to evaluation mode (disables dropout, uses running stats)
# Create example input matching expected dimensions
example_input = torch.randn(1, 3, 224, 224)
# Method 1: Tracing (for models without control flow)
traced_model = torch.jit.trace(model, example_input)
traced_model.save(save_path.replace(".pt", "_traced.pt"))
# Method 2: Scripting (handles if/else, loops)
scripted_model = torch.jit.script(model)
scripted_model.save(save_path.replace(".pt", "_scripted.pt"))
# Verify outputs match
with torch.no_grad():
original_out = model(example_input)
traced_out = traced_model(example_input)
scripted_out = scripted_model(example_input)
assert torch.allclose(original_out, traced_out, atol=1e-5)
assert torch.allclose(original_out, scripted_out, atol=1e-5)
print(f"Model exported successfully to {save_path}")
def optimize_for_inference(model_path: str) -> torch.jit.ScriptModule:
"""Load and optimize TorchScript model for inference"""
model = torch.jit.load(model_path)
# Optimize for inference (fuses operations, removes dropout)
optimized = torch.jit.optimize_for_inference(model)
return optimized
# Export ResNet18
model = models.resnet18(weights=ResNet18_Weights.IMAGENET1K_V1)
export_for_production(model, "resnet18_production.pt")Voor maximale inferentiesnelheid kan ONNX-export worden overwogen voor cross-framework compatibiliteit of TensorRT voor NVIDIA GPU-deployment. De vergelijking PyTorch vs TensorFlow behandelt deployment-afwegingen tussen frameworks.
Conclusie
Computer vision met PyTorch combineert krachtige abstracties met productie-klare tools:
- CNN-architecturen extraheren hiërarchische kenmerken door convolutie-, pooling- en normalisatielagen
- Transfer learning met voorgetrainde modellen (ResNet, EfficientNet) bereikt hoge nauwkeurigheid met beperkte data
- Data-augmentatie (MixUp, CutOut, geometrische transformaties) verbetert generalisatie en voorkomt overfitting
- Technische sollicitatiegesprekken testen receptieve velden, batch normalisatie, padding-strategieën en het omgaan met klasse-onbalans
- TorchScript maakt productie-deployment mogelijk zonder Python-afhankelijkheden
Begin met oefenen!
Test je kennis met onze gespreksimulatoren en technische tests.

Geschreven door
Anthony Fillion-MailletFullstack-ontwikkelaar, oprichter van SharpSkill
Al meer dan 10 jaar fullstack-ontwikkelaar. Hij leidt SharpSkill en staat in voor alles wat hier verschijnt.
Bijgewerkt op 14 augustus 2026
Delen
Gerelateerde artikelen

LangChain voor Data Scientists in 2026: LLMs, Agents en Sollicitatievragen
Beheers LangChain 0.3 voor data science: LCEL-chains, RAG-patronen, ReAct-agents en memory-systemen. Inclusief sollicitatievragen en productie-deployment strategieën.

MLOps in 2026: MLflow, Model Registry en technische sollicitatievragen
MLOps-sollicitatievragen over de ML-levenscyclus, MLflow experiment tracking, promotie in de model registry, uitrolpatronen, driftmonitoring en systeemontwerp voor 2026, met Python-code en antwoorden.

RAG en LLMs in 2026: Retrieval-Augmented Generation voor Data Science Sollicitaties
RAG-sollicitatiegids voor data science in 2026. Behandelt RAG-pipelines, vectordatabases, chunking, embeddings, agentic RAG en Graph RAG.