programdemos/backprop/backprop.xtl

One step of training, every array shown: a small network (2 inputs, 4 tanh units, softmax over 3 classes) on six points of a spiral. The forward pass, the loss, each layer's gradient as one expression, the step; then every gradient checked against a finite difference.

source · imports nn: libs/NN/src/NN.xtl

The batch and the starting weights, read from data/

b : Float

value · line 10
b ← 6 3 r̲eshape n̲umbers ⎕N̲GET "data/batch.txt"
Used in: X, Y

X : Float

value · line 11
X ← 2 t̲ake₂ b                          ⍝ 6 points, x and y
Used in: H, D2, G1, ᵘl̲oss

Y : Float

value · line 12
Y ← 3 ⁿⁿo̲neHot f̲loor r̲avel -1 t̲ake₂ b          ⍝ their arms, one-hot
Used in: L, D2, ᵘl̲oss

W1 : Float

value · line 13
W1 ← 3 4 r̲eshape n̲umbers ⎕N̲GET "data/w1.txt"        ⍝ 2 inputs, then the bias row
Used in: H, V1, F1, F2

W2 : Float

value · line 14
W2 ← 5 3 r̲eshape n̲umbers ⎕N̲GET "data/w2.txt"        ⍝ 4 inputs, then the bias row
Used in: P, D1, V2, F1, F2

lr : Float

value · line 15
lr ← 0.5
Used in: V1, V2

Forward

H : Float

value · line 18
H ← ⁿⁿt̲anh X ⁿⁿd̲ense W1                ⍝ 6 x 4
Used in: P, G2, D1

P : Float

value · line 19
P ← ⁿⁿs̲oftmax H ⁿⁿd̲ense W2             ⍝ 6 x 3

L : Float

value · line 20
L ← Y ⁿⁿc̲rossEntropy P

Backward: each layer's gradient, one expression each

ᵘo̲nes : Float -> Float

function · line 23
ᵘo̲nes ← { x → x c̲at₂ ((t̲ally x) c̲at 1) r̲eshape 1.0 }            ⍝ a column of 1s: the bias input
Used in: G2, G1

D2 : Float

value · line 24
D2 ← (P − Y) ÷ f̲loat t̲ally X                       ⍝ loss by the output scores (softmax with cross-entropy)
Used in: G2, D1

G2 : Float

value · line 25
G2 ← (o̲\ ᵘo̲nes H) '+ '× i̲nner D2                   ⍝ W2's gradient, 5 x 3

D1 : Float

value · line 26
D1 ← (D2 '+ '× i̲nner o̲\ -1 d̲rop W2) × 1.0 − H × H       ⍝ back through W2 and tanh
Used in: G1

G1 : Float

value · line 27
G1 ← (o̲\ ᵘo̲nes X) '+ '× i̲nner D1                   ⍝ W1's gradient, 3 x 4

The step

V1 : Float

value · line 30
V1 ← W1 − lr × G1

V2 : Float

value · line 31
V2 ← W2 − lr × G2

ᵘl̲oss : Float -> Float -> Float

function · line 32
ᵘl̲oss ← { w1 w2 → Y ⁿⁿc̲rossEntropy ⁿⁿs̲oftmax (ⁿⁿt̲anh X ⁿⁿd̲ense w1) ⁿⁿd̲ense w2 }

ᵘr̲ound : Float -> Float

function · line 35
ᵘr̲ound ← { a → (f̲loat f̲loor 0.5 + 10000.0 × a) ÷ 10000.0 }

e : Float

value · line 45

Each analytic gradient against a central finite difference, (L(w + e) - L(w - e)) / 2e for every weight: the largest difference of all 27.

e ← 0.00001
Used in: ᵘb̲ump, F1, F2

ᵘb̲ump : a -> Int -> Float

function · line 46
ᵘb̲ump ← { w i → e × f̲loat (s̲hape w) r̲eshape i = r̲ange t̲ally r̲avel w }
Used in: F1, F2

F1 : Float

value · line 47
F1 ← (s̲hape W1) r̲eshape '{ i → (((W1 + W1 ᵘb̲ump i) ᵘl̲oss W2) − (W1 − W1 ᵘb̲ump i) ᵘl̲oss W2) ÷ 2.0 × e } e̲ach r̲ange 12
Used in: gap

F2 : Float

value · line 48
F2 ← (s̲hape W2) r̲eshape '{ i → ((W1 ᵘl̲oss W2 + W2 ᵘb̲ump i) − W1 ᵘl̲oss W2 − W2 ᵘb̲ump i) ÷ 2.0 × e } e̲ach r̲ange 15
Used in: gap

gap : Float

value · line 49
gap ← ('m̲ax r̲/ r̲avel a̲bs G1 − F1) m̲ax 'm̲ax r̲/ r̲avel a̲bs G2 − F2