The learning rate was the real lever, not the network's size
The experiment taught more than a promotion would have
Building the YINSH board-game AI is the strand of this project that keeps proving where the real limits are. gen-270 — the current champion, at 3.36 million learned weights — had stopped improving. We tried growing it to a bigger brain and spent a night finding out why it didn’t work the way we expected. It didn’t promote. But the reason it didn’t was more instructive than a promotion: one hardcoded number, a learning rate we hadn’t thought to configure, was silently defeating the idea from the start.
TL;DR
- The YINSH AI improves through a four-step loop: play games against itself, train a new network on those games, test the new network against the champion, promote it if it wins convincingly.
gen-270(128 channels × 10 blocks, 3.36M weights) had stalled for 70+ generations. A bigger 160×12 network (5.95M weights) seemed like the obvious fix.- Training a fresh big network from scratch capped at ~25–29% win rate — it could only copy the champion, not surpass it.
- A technique called Net2Net grew the champion’s weights into the bigger body, starting at parity — but the default learning rate erased that advantage in one training step.
- Lowering the learning rate by a factor of ten swung the result by +154 Elo — from “reliably loses” to “nearly tied.”
- Final score: nothing beat
gen-270. But we came away with three reusable tools and a much clearer picture of what to try next.
A self-teaching loop with a strict referee
The YINSH AI has no human games to learn from. Instead it improves through a loop that repeats generation after generation:
- Self-play — the champion plays thousands of games against itself, guided by a look-ahead search that makes its moves stronger than its raw instincts.
- Train — a fresh network studies those games, learning to copy the champion’s best choices.
- Gate — the fresh network plays a match against the champion. A statistical test called SPRT keeps playing until the result is confident — not lucky — one way or the other.
- Promote — if the fresh network wins convincingly, it becomes the new champion and the loop restarts.
The gate is a ratchet: strength only ever goes up. gen-270 had survived 70 consecutive generations of challengers without losing once.
Copying a master only gets you close
Our first attempt: build a fresh 160×12 network with random weights and let it learn in the loop. It climbed to about 25–29% win rate against gen-270 and stopped. It never came close.
The reason is structural. All the training data comes from gen-270. The new network’s entire job is to imitate the champion’s play — and imitating an expert gets you close to the expert but essentially never past it. You inherit its blind spots and add your own copying errors on top. This is the distillation ceiling (named for the practice of training a “student” to copy a “teacher”). Running with stronger look-ahead search during self-play raised the ceiling slightly (+58 Elo) but leveled off at 29%. Better copies, same ceiling.
Growing the champion without losing it
If starting from random forces re-learning from scratch, why start from random?
Net2Net is a technique that takes a trained network and produces a larger one that computes the exact same function — same inputs, same outputs, down to floating-point rounding. Instead of a fresh 160×12 network at −576 Elo vs the champion, we get one that is gen-270, starting at zero gap. The extra capacity is free headroom.
Two operations make it work. Widening (adding channels): copy an existing channel’s weights into the new slot, then divide the next layer’s weights for those copies by the number of copies — so the duplicates sum back to the original contribution. Output unchanged. Deepening (adding a layer): insert a block whose “detour” is muted to zero at birth, making it a pure pass-through. As training runs, the mute gradually lifts, the detour wakes up, and the block learns to add something useful. Both were verified with a parity check: outputs within 0.000001 on random inputs, before a single training step. 3.36M parameters → 5.95M, identical play.
One number erased the warm-start
We grew gen-270 to 160×12 and launched training. After one generation it was back at ~25% — same as from scratch. Growing it had apparently bought nothing.
The culprit: the learning rate (LR). Training adjusts a network’s weights by taking small steps in the direction that improves play. The LR is the step size. Picture the space of all possible weight configurations as a landscape where height equals strength. gen-270’s weights sit on a narrow peak. Starting there (the warm-start) puts us on the peak. The LR then decides whether we stay:
- LR = 1e-3 (the default): tuned for training from random, where large exploratory steps are desirable. Applied to a network already on the peak, it leaps off on the first step. The warm-start is erased.
- LR = 1e-4 (fine-tune): ten times smaller. The network stays near the peak and makes small adjustments. Champion strength is preserved.
| Learning rate | Generation-1 strength vs champion |
|---|---|
| LR = 1e-3 (default) | −195 Elo (24.5% win) |
| LR = 1e-4 (fine-tune) | −41 Elo (44% win) |
One number, +154 Elo swing. The LR had been hardcoded in the training script and not exposed as an option; plumbing it through as a configurable flag was the entire fix (PR #1439). Warm-start and learning rate are coupled: starting from a strong point only helps if your step size is small enough to stay near it.
What this changes going forward
With the fine-tune LR, the grown network settled at ~45–49% win rate — matching the champion but not beating it. We tried one more lever: switching self-play from the frozen champion to the latest network. This is how AlphaZero actually exceeds its starting point — training on its own ever-improving play. But our network was sitting just below parity; its games were slightly weaker than the champion’s, and training on them drifted it downward to ~40%. The switch to self-improvement requires being at or above the teacher first.
gen-270 stays champion. The grown network (PR #1436), the LR flag (PR #1439), and a straggler barrier that stops a generation waiting for one slow game (PR #1444) are the three tools we leave with. When the network next reaches genuine parity under fine-tune LR, the warm=latest switch is the next lever.
Keywords
- Self-play — the AI generates its own training examples by playing games against itself, with no human games needed.
- Champion — the current best network; candidates must beat it in a statistical match before replacing it.
- Gate (SPRT) — a statistical test that plays only as many games as needed to be confident the result is real, not due to luck.
- Elo — a strength score; a +100 Elo gap means the stronger side wins roughly 64% of the time.
- Generation — one full pass of the loop: self-play, train, gate, promote-or-discard.
- Distillation ceiling — the limit a “student” network copying a frozen “teacher” tends to hit: it approaches the teacher’s strength but rarely exceeds it.
- Net2Net — a technique that expands a trained network into a larger one computing the same function, so the bigger model inherits the smaller one’s skill instead of starting from zero.
- Learning rate — how large a step training takes when adjusting a network’s weights; too large a step on a warm-started network erases what the warm-start gave you.
- Warm-start — beginning training from an existing network’s weights rather than from random initialization.
- Residual block — a standard deep-network building block with two paths: a shortcut that carries the input unchanged, plus a “detour” branch that learns an adjustment to add on top.
References
training/yinsh-ai/src/net2net.py,training/yinsh-ai/tests/test_net2net.py— the grow utility and parity tests; PR#1436.packages/yinsh-ai-core/scripts/iterate.ts,training/yinsh-ai/run-campaign-k3s.sh— the--lrflag plumbing; PR#1439.- PR
#1444— the self-play straggler soft-barrier: trains on the 95% of games that finish on schedule, skips the rest. docs/task-log/20260717-ai-training-improvement/02-next-levers.md— the full experiment table with every configuration and Elo reading.docs/task-log/20260717-ai-training-improvement/03-how-ai-training-works.md— the teaching document this post is adapted from, written for a junior AI engineer.- [[2026-07-14-clever-tricks-lost-to-capacity]] — the 270-generation retrospective; the capacity plateau this experiment tried to break.
- [[2026-06-29-capacity-was-the-limiter]] — how the first capacity ceiling was broken (96×8 → 128×10, +113 Elo).
- AlphaZero (DeepMind, 2017) — the self-play + search + train loop this pipeline copies.
- Net2Net: Accelerating Learning via Knowledge Transfer (Chen et al., 2016) — the original paper behind the grow technique.
AI workflow note
The source material (03-how-ai-training-works.md) was written first as a teaching document for a junior AI engineer, with all experiments already complete and numbers cited. Adapting it for a non-engineer post meant selecting the two or three ideas a lay reader could follow end-to-end (the loop, the distillation ceiling, the learning rate trap) and cutting the pedagogical scaffolding (“junior takeaway” boxes, gradient-flow depth). The Net2Net section was the hardest translation: “copy + split credit” and “zero-volume detour” are precise in the source but require two concepts arriving at once; solving it meant leading with the analogy (the narrow peak) before the mechanism. The learning rate section adapted with almost no rework — the mental model was already non-engineer-legible in the source document.
