DAI-utvecklareLaboration· ca 75 min· sandlåda på servern
Labb: ett neuronnät i ren NumPy — forward, backprop, gradientkontroll
Implementera forward pass, loss, backprop och träningsloop för ett tvålagersnät, verifiera gradienterna numeriskt och lära nätet XOR.
Teori
z₁ = W₁x + b₁, a₁ = ReLU(z₁), z₂ = W₂a₁ + b₂, L = ½‖z₂ − y‖². Bakåt: δ₂ = z₂ − y; ∂L/∂W₂ = δ₂a₁ᵀ; δ₁ = (W₂ᵀδ₂) ⊙ 1[z₁>0]; ∂L/∂W₁ = δ₁xᵀ. Den numeriska kontrollen (L(w+ε) − L(w−ε))/2ε avslöjar varje fel i härledningen.
Deluppgifter
- forward —
forward(params, X)returnerar (z1, a1, z2) för en batch X (n×d). - backward —
backward(params, X, Y, cache)returnerar gradienter för W1, b1, W2, b2 (medel över batchen). - träna —
train(X, Y, hidden, lr, steps, seed)tränar med gradient descent och returnerar params.
Godkänt när: loss <= 0.05
Startkoden
körs i en isolerad sandlåda på servernimport numpy as np
def init(d, h, k, seed=0):
rng = np.random.default_rng(seed)
return {"W1": rng.normal(0, 0.5, (h, d)), "b1": np.zeros(h), "W2": rng.normal(0, 0.5, (k, h)), "b2": np.zeros(k)}
def forward(p, X):
"""X: (n, d). Returnerar (z1, a1, z2) med former (n, h), (n, h), (n, k)."""
# TODO
...
def loss(z2, Y):
return 0.5 * float(np.mean(np.sum((z2 - Y) ** 2, axis=1)))
def backward(p, X, Y, cache):
"""cache = (z1, a1, z2). Returnerar dict med dW1, db1, dW2, db2 (medel över batchen)."""
# TODO
...
def train(X, Y, hidden=8, lr=0.5, steps=3000, seed=0):
p = init(X.shape[1], hidden, Y.shape[1], seed)
# TODO: loop: forward → backward → uppdatera alla parametrar
...
return p
Du skriver koden, tester du inte ser avgör om den håller. Skapa ett gratis konto för att köra labben.
Prova diagnosenSkapa konto gratisFörväntade resultat
Gradientkontrollen ger relativ skillnad < 1e-5 för alla parametrar. XOR-lossen efter 3000 steg < 0.05.
Vanliga fel
- ReLU-derivatan glömd → δ₁ = W₂ᵀδ₂ utan maskering (gradientkontrollen för W1 faller).
- Transponat fel: W₁ är h×d, så ∂L/∂W₁ = δ₁ᵀ-form beror på din layout — håll fast vid en.
- Medelvärde över batchen saknas → gradienten n gånger för stor.