Machine Learning Academy · Les

Convolutie en filters: randen en patronen detecteren

Cursisten passen een handgemaakte randdetectiekernel toe op een afbeelding, laten nn.Conv2d vervolgens automatisch filters leren en bekijken de gewichten na het trainen.

Les 1 van 413 stappen

Convolutie en filters: randen en patronen detecteren is een gratis Machine Learning Academy-les op CoddyKit. Dit is les 1 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.

Wat is een convolutiebewerking?

Convolutie is een wiskundige bewerking waarbij een kleine matrix, een filter (of kernel), over een invoer (bijvoorbeeld een afbeelding) schuift en op elke positie een elementsgewijs inwendig product berekent. Het resultaat is een kenmerkenkaart die laat zien waar het door de filter weergegeven patroon in de invoer voorkomt. In beeldverwerking detecteren verschillende filters verschillende kenmerken: randen, hoeken, texturen of concepten op een hoger niveau wanneer ze in meerdere lagen worden gestapeld.

import torch

# Manual 2D convolution (single filter)
image = torch.tensor([
    [1., 0., 1., 0.],
    [0., 1., 0., 1.],
    [1., 0., 1., 0.],
    [0., 1., 0., 1.]
]).unsqueeze(0).unsqueeze(0)  # shape: (1,1,4,4)

# Vertical edge detector filter
filter_ = torch.tensor([[[-1., 1., -1.],
                          [-1., 1., -1.],
                          [-1., 1., -1.]]]).unsqueeze(0)  # (1,1,3,3)

import torch.nn.functional as F
feature_map = F.conv2d(image, filter_, padding=0)
print(feature_map.shape)   # (1, 1, 2, 2)

Filters en randdetectie

Klassieke beeldverwerking gebruikt handmatig ontworpen filters: de Sobel-filter detecteert horizontale of verticale randen, de Laplaciaanfilter detecteert alle randen en de Gaussiaanse filter maakt afbeeldingen waziger (gladder). In deep learning worden deze filters uit gegevens geleerd in plaats van handmatig ontworpen. Het belangrijkste inzicht achter CNN's is dat het netwerk automatisch ontdekt welke filters nuttig zijn voor de taak door de trainingsfout te minimaliseren.

import torch
import torch.nn.functional as F

# Sobel horizontal edge detector
sobel_h = torch.tensor([[
    [-1., -2., -1.],
    [ 0.,  0.,  0.],
    [ 1.,  2.,  1.]
]]).unsqueeze(0)   # shape (1, 1, 3, 3)

# Create a simple gradient image (brightness increases left->right)
image = torch.arange(16.).reshape(1, 1, 4, 4)
feature_map = F.conv2d(image, sobel_h, padding=1)
print('Edge response shape:', feature_map.shape)
print('Edge values:', feature_map.squeeze())

nn.Conv2d: parameters uitgelegd

nn.Conv2d(in_channels, out_channels, kernel_size) is de kernlaag van een CNN. in_channels is het aantal invoerkanalen (3 voor RGB-afbeeldingen), out_channels is het aantal filters dat moet worden geleerd en kernel_size is de ruimtelijke grootte van elke filter (3 betekent 3x3). Elke filter produceert één uitvoerkanaal, dus 64 filters produceren een kenmerkenkaart met 64 kanalen. Het totale aantal parameters in één Conv2d-laag is out_channels * in_channels * kernel_h * kernel_w + out_channels (bias).

import torch
import torch.nn as nn

# 3-channel (RGB) input -> 64 feature maps, 3x3 filters
conv = nn.Conv2d(
    in_channels=3,
    out_channels=64,
    kernel_size=3,
    padding=1,     # 'same' padding: output same size as input
    stride=1       # move filter by 1 pixel at a time
)
print('Filter shape:', conv.weight.shape)  # (64, 3, 3, 3)
# 64 filters, each 3x3 applied to 3 channels

params = 64 * 3 * 3 * 3 + 64  # weights + bias
print('Parameters:', params)   # 1792

Padding en stride

Padding voegt nullen toe rond de rand van de invoer voordat de convolutie wordt uitgevoerd. padding=1 met een filter van 3x3 behoudt de ruimtelijke afmetingen van de invoer (same-padding). Zonder padding verkleint elke convolutie de breedte en hoogte met kernel_size - 1. Stride bepaalt hoeveel pixels de filter bij elke stap verschuift. stride=2 halveert de uitvoerafmetingen en werkt als een lichte poolingbewerking. Convoluties met stride 2 worden in moderne CNN's vaak gebruikt in plaats van expliciete pooling.

import torch
import torch.nn as nn

# Output size formula: floor((W - K + 2P) / S) + 1
# W=input, K=kernel, P=padding, S=stride

x = torch.randn(1, 3, 32, 32)  # single 32x32 RGB image

conv_same = nn.Conv2d(3, 16, 3, padding=1, stride=1)
print(conv_same(x).shape)  # (1, 16, 32, 32) -- same size

conv_down = nn.Conv2d(3, 16, 3, padding=1, stride=2)
print(conv_down(x).shape)  # (1, 16, 16, 16) -- halved

conv_no_pad = nn.Conv2d(3, 16, 3, padding=0, stride=1)
print(conv_no_pad(x).shape)  # (1, 16, 30, 30) -- reduced

Meerdere kanalen: invoer en uitvoer

Een kleurenafbeelding heeft 3 kanalen (R, G, B). Elke filter in een Conv2d-laag heeft een diepte die gelijk is aan in_channels: de filter werkt tegelijk over alle invoerkanalen en produceert per ruimtelijke positie één enkele uitvoerwaarde. Met 64 filters krijg je 64 uitvoerkanalen. De volgende convolutielaag gebruikt deze 64 kanalen vervolgens als invoer. Door kanalen op deze manier te stapelen kan het netwerk steeds abstractere representaties opbouwen, van eenvoudige kleurranden tot onderdelen van objecten op een hoger niveau.

import torch
import torch.nn as nn

# Layer 1: RGB (3ch) -> 32 feature maps
conv1 = nn.Conv2d(3, 32, 3, padding=1)
# Layer 2: 32 feature maps -> 64 feature maps
conv2 = nn.Conv2d(32, 64, 3, padding=1)

x = torch.randn(4, 3, 28, 28)  # batch of 4 MNIST-like images
out1 = torch.relu(conv1(x))
print('After conv1:', out1.shape)  # (4, 32, 28, 28)
out2 = torch.relu(conv2(out1))
print('After conv2:', out2.shape)  # (4, 64, 28, 28)

Parameterefficiëntie: gewichten delen

Een belangrijk voordeel van convoluties is het delen van gewichten: dezelfde filter wordt op elke ruimtelijke positie toegepast. Een filter van 3x3 op een afbeelding van 256x256 gebruikt 9 parameters, ongeacht de afbeeldingsgrootte. Een volledig verbonden laag zou daarentegen miljoenen parameters nodig hebben. Hierdoor zijn CNN's voor afbeeldingsgegevens veel parameterefficiënter dan MLP's en hebben ze translatie-equivariantie: een verschoven versie van een patroon in de invoer produceert een overeenkomstig verschoven kenmerkenkaart.

# Parameter comparison: Conv vs FC for 256x256 images
image_size = 256 * 256

# Convolution: 3x3 filter, 1 input channel, 1 output channel
conv_params = 3 * 3 * 1 + 1   # 10 parameters

# Fully connected: every input pixel connects to every output
fc_params = image_size * image_size  # 4 billion params!

print(f'Conv params:    {conv_params}')
print(f'FC params:      {fc_params:,}')
print(f'Ratio: {fc_params / conv_params:.1e}x fewer parameters for convolution')

Wat filters leren in CNN's

Het visualiseren van geleerde filters onthult een hiërarchie van geleerde kenmerken. Filters in de eerste laag detecteren meestal georiënteerde randen, kleurverlopen en texturen — vergelijkbaar met handmatig ontworpen Sobel-filters. Filters in middelste lagen detecteren combinaties daarvan: krommen, hoeken en texturen. Filters in diepe lagen reageren op onderdelen van objecten (ogen, wielen, veren). Dit hiërarchische leren van kenmerken verklaart waarom diepe CNN's oppervlakkige modellen sterk overtreffen bij taken voor beeldherkenning.

import torch
import torch.nn as nn

# Visualise first-layer filter weight ranges
conv1 = nn.Conv2d(3, 64, 3, padding=1)
print('Filter weights shape:', conv1.weight.shape)
# (64, 3, 3, 3) -- 64 filters, each 3x3 for 3 RGB channels

# One filter: 3-channel 3x3 spatial pattern
filter_0 = conv1.weight[0]   # shape: (3, 3, 3)
print('Filter 0 (R channel):')
print(filter_0[0].detach())  # 3x3 pattern for Red channel
# After training, this would show edge-like patterns

Receptief veld: wat elke neuron ziet

Het receptieve veld van een neuron in een CNN is het gebied van de oorspronkelijke invoerafbeelding dat bijdraagt aan de activatie ervan. Eén convolutielaag met een filter van 3x3 heeft een receptief veld van 3x3. Twee gestapelde lagen met filters van 3x3 geven een receptief veld van 5x5. Drie lagen geven 7x7. Veel kleine filters stapelen is parameterefficiënter dan één grote filter en levert hetzelfde receptieve veld op. Daarom gebruiken moderne CNN's bijna uitsluitend filters van 3x3 — geïnspireerd door de bevindingen rond VGGNet.

# Receptive field grows with depth
# Each 3x3 conv adds 2 to each side of the receptive field

def receptive_field(n_layers, kernel_size=3):
    rf = 1
    for _ in range(n_layers):
        rf += (kernel_size - 1)
    return rf

for n in [1, 2, 3, 5, 10, 20]:
    rf = receptive_field(n)
    print(f'{n} layers of 3x3: receptive field = {rf}x{rf}')
# 1 -> 3, 2 -> 5, 3 -> 7, 5 -> 11, 10 -> 21, 20 -> 41

Een eenvoudig CNN-blok bouwen

Het standaard-CNN-blok volgt het patroon: Conv2d -> BatchNorm2d -> ReLU -> (optionele pooling). Dit drietal wordt meerdere keren herhaald met steeds meer kanalen, waarbij de ruimtelijke afmetingen geleidelijk afnemen en het aantal kenmerkkanelen toeneemt. De ruimtelijke verkleining comprimeert locatie-informatie, terwijl de uitbreiding van het aantal kanalen meer abstracte kenmerken vastlegt. Dit patroon vormt de basis van ResNet, VGG, EfficientNet en de meeste andere architecturen.

import torch
import torch.nn as nn

def conv_block(in_ch, out_ch):
    return nn.Sequential(
        nn.Conv2d(in_ch, out_ch, 3, padding=1),
        nn.BatchNorm2d(out_ch),
        nn.ReLU(inplace=True)
    )

model = nn.Sequential(
    conv_block(3, 32),    # 3 -> 32 channels
    nn.MaxPool2d(2),      # halve spatial size
    conv_block(32, 64),   # 32 -> 64 channels
    nn.MaxPool2d(2),
    conv_block(64, 128),  # 64 -> 128 channels
)

x = torch.randn(4, 3, 32, 32)
print(model(x).shape)   # (4, 128, 8, 8)

Filteractivaties visualiseren

Na het trainen kun je kenmerkkaarten (filteractivaties) voor een specifieke invoerafbeelding visualiseren om te zien wat elke filter heeft gedetecteerd. Heldere gebieden in een kenmerkkaart geven aan waar het bijbehorende filterpatroon is gedetecteerd. Dit is nuttig voor het opsporen van fouten (controleren of vroege lagen randdetectoren hebben geleerd) en voor uitlegbaarheid (laten zien welke gebieden van een afbeelding een detector voor 'honden vacht' of 'wiel' in latere lagen hebben geactiveerd).

import torch
import torch.nn as nn

# Extract feature maps after the first conv layer
conv1 = nn.Conv2d(3, 8, 3, padding=1)
relu = nn.ReLU()

x = torch.randn(1, 3, 16, 16)   # single image
feature_maps = relu(conv1(x))   # shape: (1, 8, 16, 16)

print('Number of feature maps:', feature_maps.shape[1])  # 8
print('Feature map size:', feature_maps.shape[2:])        # 16x16

# Plot with matplotlib:
# import matplotlib.pyplot as plt
# fig, axes = plt.subplots(1, 8)
# for i, ax in enumerate(axes):
#     ax.imshow(feature_maps[0, i].detach(), cmap='gray')

1x1-convoluties: kanalen mengen

1x1-convoluties passen op elke ruimtelijke positie een lineaire combinatie over de kanalen toe, zonder ruimtelijke menging. Ze worden gebruikt om het aantal kanalen goedkoop te verkleinen of uit te breiden (zoals in de Inception- en MobileNet-bottleneckontwerpen). Een 1x1-convolutie van 256 naar 64 kanalen vermindert de berekening in de daaropvolgende 3x3-convolutie met een factor 16. Ze introduceren ook niet-lineariteit (via activatie) tussen stappen waarin kanalen worden gemengd, waardoor de modelcapaciteit toeneemt tegen minimale kosten in parameters.

import torch
import torch.nn as nn

# Bottleneck block: expand -> 3x3 conv -> compress
bottleneck = nn.Sequential(
    nn.Conv2d(256, 64, 1),   # 1x1: channel reduction
    nn.ReLU(),
    nn.Conv2d(64, 64, 3, padding=1),  # 3x3: spatial mixing
    nn.ReLU(),
    nn.Conv2d(64, 256, 1),   # 1x1: channel expansion
    nn.ReLU()
)

x = torch.randn(4, 256, 14, 14)
out = bottleneck(x)
print(out.shape)   # (4, 256, 14, 14) -- same shape as input

Korte controle

Toets je begrip van de concepten uit deze les over Machine Learning met Python.

Samenvatting van de les

In deze les heb je geleerd dat convolutie een filter over de invoer schuift en daarbij inproducten berekent om een kenmerkkaart te maken die aangeeft waar het filterpatroon voorkomt, dat de parameters van nn.Conv2d (in_channels, out_channels, kernel_size, padding, stride) de filterbank bepalen, en dat gewichtsdelen convoluties voor ruimtelijke gegevens veel efficiënter maken met parameters dan volledig verbonden lagen. Hierna bekijken we poolinglagen voor ruimtelijke verkleining en translatie-invariantie.

Gratis beginnen

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 “Convolutie en filters: randen en patronen detecteren” gratis?

Ja — de volledige tekst van “Convolutie en filters: randen en patronen detecteren” 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 “Convolutie en filters: randen en patronen detecteren”?

Cursisten passen een handgemaakte randdetectiekernel toe op een afbeelding, laten nn.Conv2d vervolgens automatisch filters leren en bekijken de gewichten na het trainen. 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 1 van 4.

Hoe lang duurt de les “Convolutie en filters: randen en patronen detecteren”?

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

  1. Convolutie en filters: randen en patronen detecteren
  2. Poolinglagen: ruimtelijke downsampling en invariantie
  3. Een CNN bouwen en trainen op CIFAR-10
  4. Data-augmentatie: transformaties voor robuustheid
← Terug naar Machine Learning Academy