- Je rekent een batch door met XW+b en controleert de vormen.
- Je verklaart waarom meer affine lagen zonder activatie geen nieuwe modelklasse opleveren.
Eén neuron verwerkt één voorbeeld en geeft één score. Nu wil je meerdere scores per plant én meerdere planten tegelijk verwerken, met dezelfde instellingen voor iedere plant. Een dense laag bundelt de gewogen sommen in een matrixberekening.
Iedere rij is één voorbeeld en iedere kolom één feature. Zo'n groep voorbeelden heet een batch. De batchgrootte verandert hoeveel je tegelijk doorrekent; zij voegt geen nieuwe modelgewichten toe.
1. Laat de binnenste maten overeenkomen
Neem twee planten met features [1,2] en [3,4]. We maken twee uitvoerscores met gewichtenmatrix W = [[1,−1],[2,0]] en biasvector [0.5,1]. Een kolom van W bevat de gewichten van één uitvoerneuron.
Voor de eerste plant wordt score 1 gelijk aan 1×1+2×2+0.5 = 5.5. Score 2 wordt 1×(−1)+2×0+1 = 0. Voor de tweede plant krijg je 11.5 en −2.
Bij n voorbeelden, d invoerfeatures en h uitvoerneuronen heeft X vorm (n,d), W vorm (d,h) en b vorm (h,). Z krijgt vorm (n,h). De binnenste maat d verbindt de matrices; de bias wordt bij iedere uitvoerrij opgeteld.
import numpy as np
X = np.array([[1, 2], [3, 4]], dtype=float)
W = np.array([[1, -1], [2, 0]], dtype=float)
b = np.array([0.5, 1.0])
Z = X @ W + b
print(Z.tolist())
# [[5.5,0.0],[11.5,-2.0]]
print(X.shape, W.shape, b.shape, Z.shape)
# (2,2) (2,2) (2,) (2,2)
np.array maakt een NumPy-array en dtype=float kiest opslag met kommagetallen. .shape geeft de aslengtes; .ndim telt de assen. @ is het matrixproduct, terwijl NumPy de bias hier automatisch over de rijen herhaalt: broadcasting.
Maak dense(x,w,b) en geef een NumPy-array terug. Zet de invoer om met np.asarray(...,dtype=float), zodat ook lijsten bruikbaar zijn. Controleer vóór het product dat x en w tweedimensionaal zijn, b eendimensionaal is, de binnenste maten overeenkomen en iedere uitvoerkolom één bias heeft; anders geef je ValueError.
Een toevallig broadcastbare b met vorm (1,h) voldoet dus niet aan ons afgesproken vectorcontract. De vormcontrole maakt een verkeerd model zichtbaar vóór NumPy misschien een andere berekening uitvoert.
Elk vakje is één getal. Deze vaste voorbeeldwaarden veranderen mee met de gekozen vormen.
Bias b = [0.0, 0.1, 0.2], eenmaal per uitvoerneuron. Matrixvakjes tonen één decimaal; de uitvoerrij twee.
Verhoog in het diagram alleen n. Voorspel welke matrix groter wordt en of het parameteraantal verandert. Verhoog daarna h en controleer zowel het aantal kolommen als de extra biases.
012. Tel gewichten en biases afzonderlijk
Een laag met d invoeren en h uitgangen heeft d×h gewichten en h biases. Bij breedtes [2,3,1] heeft de eerste laag 2×3+3 = 9 parameters. De tweede heeft 3×1+1 = 4: samen 13.
widths = [2, 3, 1]
totaal = 0
for i in range(len(widths) - 1):
d, h = widths[i], widths[i+1]
aantal = d * h + h
print(aantal) # eerst 9, daarna 4
totaal = totaal + aantal
print(totaal) # 13
Maak parameter_aantal(widths) voor minstens twee positieve gehele breedtes. De batchgrootte staat niet in deze lijst: dezelfde gewichten worden voor ieder voorbeeld gebruikt. Veelgemaakte fout: alleen matrixcellen tellen en de biasvectoren vergeten.
3. Vouw twee lagen zonder activatie samen
Een gewogen som zonder bias is lineair; met een bias heet zij affien. Twee affine lagen achter elkaar blijven samen één affine laag. De eerste bias wordt daarbij ook door de tweede gewichtenmatrix vermenigvuldigd.
Neem W₁ = [[1,0],[0,2]], b₁ = [1,−1], W₂ = [[2],[3]] en b₂ = [0.5]. De gecombineerde gewichten worden [[2],[6]] en de bias 1×2−1×3+0.5 = −0.5. Onze twee planten krijgen daarmee 13.5 en 29.5.
W1 = np.array([[1., 0.], [0., 2.]])
b1 = np.array([1., -1.])
W2 = np.array([[2.], [3.]])
b2 = np.array([0.5])
samen_W = W1 @ W2
samen_b = b1 @ W2 + b2
twee = (X @ W1 + b1) @ W2 + b2
een = X @ samen_W + samen_b
print(twee.tolist()) # [[13.5],[29.5]]
print(np.allclose(een, twee)) # True
allclose vergelijkt getallen met ruimte voor afronding. Maak vouw_samen(w1,b1,w2,b2) als (w,b) voor passende laagvormen. Alleen b₁+b₂ optellen zou het effect van de tweede laag op de eerste bias missen.
Met een activatie ertussen geldt dit samenvoegen in het algemeen niet meer. Gebruik voor één nieuwe rij de bekende ReLU, nu elementgewijs met np.maximum:
u = np.array([[-1., -1.]])
h = np.maximum(0, u @ W1 + b1)
print((h @ W2 + b2).tolist()) # [[0.5]]
print((u @ samen_W + samen_b).tolist())
# [[-8.5]]
De verborgen som [0,−3] wordt door ReLU [0,0]. Die knik verklaart het verschil: meerdere lagen krijgen pas met zulke omzettingen extra vormen van gedrag.
03Wat neem je mee?
- Matrixvormen leggen vast welke voorbeelden, features en uitgangen je combineert.
- Parameters horen bij de laag; meer voorbeelden vergroten alleen de batch.
- Twee affine lagen zijn samen te vouwen, maar een niet-lineaire activatie verandert dat.
Hierna onderzoek je hoe activaties zowel waarden als leersignalen doorgeven.