Think of a game console: the console never changes, you swap the cartridge.
| Model | |
|---|---|
| Trained | the tic-tac-toe demo's network, trained on every position |
| Hand-written | 48 hand-set hidden units: win if you can, else block, else centre, corner, edge |
| Random | untrained: random int8 weights |
Each one is an 18 → 64 → 9 network with int8 weights. The page keeps them as three CSS rules of 1,801 numbers each and nothing else. Change the numbers and the same interpreter plays something else.
To use the cartridge, the console has to multiply its numbers, but a network can't multiply two of its inputs, only add them up. So it splits each number into pieces, like 5 = 4 + 1, and turns 5 × 7 into 4 × 7 + 1 × 7: just adding.
A ReLU network can only add up its inputs with fixed weights, and here the model's weights are inputs too. So every weight × activation is built from ReLUs. The weights come in as unsigned bytes u = w + 128.
| Step | As ReLU |
|---|---|
| layer 1: x is 0 or 1 | x · u = relu(u − 256·(1 − x)), then subtract 128·Σx |
| a byte's bits, all at once | q_j = ⌊u / 2^j⌋ = round(relu(2u + 1 − 2^j) / 2^(j+1)), bit_j = q_j − 2·q_(j+1) |
| bit × activation, 0 ≤ h ≤ 3,310 | relu(h − 3,310·(1 − bit)) |
| w × h | −128·(sign·h) + Σ_j<7 2^j·(bit_j·h), two's complement |
| then | step 1's rules: the best free square, if you moved and the game is on |