kings-vision-models / README.md
FlappingChance's picture
model card
eb7fed3 verified
|
Raw
History Blame Contribute Delete
12.2 kB
---
license: mit
library_name: onnxruntime
tags:
- chess
- onnx
- gan
- computer-vision
---
# King's Vision — models
ONNX artifacts for [King's Vision](https://github.com/RyanMatthew04/kings-vision):
mate-in-one puzzle generators steered by a Cross-Entropy Method search, and a
board square classifier that reads a chessboard image into a FEN.
Every model runs on `onnxruntime` alone — no TensorFlow, no PyTorch.
```python
from huggingface_hub import hf_hub_download
import onnxruntime as ort
path = hf_hub_download("FlappingChance/kings-vision-models", "queen_mate_generator.onnx")
session = ort.InferenceSession(path)
```
The application fetches these automatically; see `src/kings_vision/artifacts.py`.
---
## mate-type generators and CEM agents
Five DCGAN generators that synthesise chess checkmate positions, each paired with
a multi-modal Cross-Entropy Method agent that steers its latent input.
| | |
|---|---|
| **Version** | 1.0 (weights migrated from the original Keras training run; not retrained) |
| **Format** | ONNX opset 18, float32, single self-contained file |
| **Size** | 20.8 MB per generator · 8.8 KB per CEM agent |
| **Parameters** | 5,193,997 per generator |
| **Licence** | MIT (this repository) |
| **Contact** | https://github.com/RyanMatthew04/kings-vision/issues |
## Intended use
Generating mate-in-one training puzzles for the King's Vision trainer. The
generator produces a *finished* checkmate; `kings_vision.puzzles.backtrack`
reconstructs the position one move earlier and verifies by replaying forward.
**Out of scope.** These models do not play chess, do not evaluate positions, and
have no notion of a game. They sample from a distribution over checkmate-shaped
board states. They are not a substitute for a curated puzzle set such as the
Lichess database, which carries human difficulty ratings these do not.
## Architecture
Generator: 100-d latent → `Dense(32768)``Reshape(8, 8, 512)` → four
`Conv2DTranspose` blocks (256 → 128 → 64 → 32, stride 1, `same` padding, kernels
3/3/5/5), each with `LeakyReLU(0.2)` and batch normalisation → `Conv2D(13, k=7)`
→ softmax over the channel axis.
Output is an 8×8×13 tensor: channel 0 is an empty square, 1–6 are white
pawn…king, 7–12 are black. `argmax` per square decodes it to a board. That
encoding is shared with the board classifier — see `kings_vision.core.encoding`.
## Training data
**The training data no longer exists.** The original run derived checkmate
positions from Lichess PGN archives, split them by mating piece into five
datasets, and trained one generator per mate type. Neither the intermediate CSV
nor the extraction script survived into either predecessor repository or its
history.
This is a real limitation and the main reason these weights were migrated rather
than retrained: they are not reproducible from anything in this repository. The
pipeline in `ml/data/` reconstructs the *method*, not the exact dataset.
## Training procedure
Recovered from telemetry embedded in the original notebook
(`docs/data/gan_training_log.csv`):
- 10,000 epochs, batch size 128, Adam
- ≈67 minutes wall clock on CPU
- Discriminator settles at 46–50% accuracy — near chance, the healthy adversarial
equilibrium — after an unstable first ~800 epochs
The inherited README claimed 200–300 epochs at batch 32 over 2–4 hours. None of
those figures matched the logs.
## The CEM agents
Each agent is five Gaussians over the generator's 100-dimensional input, trained
by Cross-Entropy Method against a binary reward (is this a legal checkmate?) with
a penalty for repeating a position. **The generator's weights are frozen.** Only
the input distribution is optimised, which is why the learned artifact is 8.8 KB
rather than another 20.8 MB.
One shipped agent (queen) has a mode whose weight decayed to 2×10⁻¹⁴ — an
effectively collapsed mode. `MultiModalCEM.collapsed_modes` reports this.
## Evaluation
`python -m ml.eval.eval_gan --n 1000 --seed 0`, Wilson intervals on validity and
bootstrap intervals on uniqueness:
| Mate type | Valid, raw | Valid, + CEM | Δ | Unique, raw | Unique, + CEM | Δ | Puzzle yield |
|---|--:|--:|--:|--:|--:|--:|--:|
| Queen | 47.4% | 88.2% | +40.8 | 100.0% | 50.8% | −49.2 | 83.6% |
| Rook | 62.1% | 77.6% | +15.5 | 100.0% | 73.7% | −26.3 | 73.6% |
| Bishop | 40.8% | 73.6% | +32.8 | 99.3% | 62.6% | −36.6 | 72.5% |
| Knight | 53.4% | 93.9% | +40.5 | 100.0% | 73.1% | −26.9 | 93.7% |
| Pawn | 46.9% | 82.7% | +35.8 | 99.8% | 74.8% | −24.9 | 27.5% |
| **Mean** | **50.1%** | **83.2%** | **+33.1** | **99.8%** | **67.0%** | **−32.8** | **70.2%** |
"Valid" is the fraction of samples that are legal positions in which the side to
move is genuinely checkmated. "Unique" is the distinct fraction among valid
samples. "Puzzle yield" is the fraction of all samples that convert to a
mate-in-one with exactly one solution.
## Limitations and honest caveats
**Diversity is traded for validity, roughly one for one.** Concentrating
probability mass on elite samples is simultaneously what raises the hit rate and
what narrows the output distribution. The diversity-aware reward limits this but
does not remove it. Anyone wanting maximum variety should sample unsteered and
filter, accepting a ~50% rejection rate.
**Validity overstates usefulness for pawn mates.** 82.7% valid but only 27.5%
convert to a unique-solution puzzle, because a pawn has few squares it could have
come from. Judge by puzzle yield, not validity.
**Puzzles are non-capturing mates.** The backtracking construction moves a piece
backwards to an empty square, so mates delivered by a capture are unreachable.
Discovered and promotion mates are reachable.
**No difficulty rating.** These puzzles are not calibrated to human skill. Every
one is mate-in-one, but "mate in one" spans a wide difficulty range and nothing
here estimates where a given puzzle sits.
**Positions are synthetic.** They are legal and reachable-looking, but not drawn
from real games, and some carry the slightly artificial texture of GAN output.
**Numerical fidelity.** The ONNX artifacts agree with the original Keras models
to 100% argmax agreement across fixed-seed reference batches — identical puzzles,
verified by `ml/export/build_onnx_generator.py`. Probability residuals of ~1e−5
are float32 accumulation differences across frameworks.
## Ethical considerations
Low risk. The models generate chess positions. They carry no personal data, and
the training corpus was public game archives. The most plausible harm is a user
being served an artificial-feeling puzzle, which the limitations above cover.
---
## board square classifier
A 13-class CNN that reads one square of a chessboard image. Sixty-four
invocations produce a position.
| | |
|---|---|
| **Version** | 1.0 |
| **Format** | ONNX opset 18, float32, single self-contained file |
| **Size** | ~0.4 MB |
| **Parameters** | 95,373 |
| **Input** | `(N, 3, 32, 32)` uint8-valued float, **0–255** |
| **Output** | `(N, 13)` logits |
| **Licence** | MIT |
Scaling to `[0, 1]` happens *inside* the graph. The serving code passes raw
pixel values and there is no preprocessing contract to get subtly wrong, which
is a common and silent source of train/serve skew.
## Intended use
Turning a screenshot of a chessboard into a FEN, so a position can be analysed
without retyping it. Output is a *placement* only — a picture cannot show whose
move it is, and the API returns the placement field rather than inventing the
rest.
**Out of scope.** Photographs of physical boards (this is trained on rendered
2D boards), boards at an angle, 3D piece sets, and any board that is not
axis-aligned and square in the crop.
## Classes
Channel order is shared with the mate generators — the same 8×8×13 encoding they
emit into. `0` empty, `1–6` white pawn…king, `7–12` black.
## Training data
**Fully synthetic, and that is the interesting part.** No corpus of screenshotted
boards with per-square labels exists, and none is needed: rendering a known
position makes every label exact and free.
`ml/data/render_boards.py` draws positions sampled from random legal playouts —
real piece densities and structures, including near-empty endgames — then
degrades them the way a screenshot is degraded between a website and a file:
rendered at 3× and downsampled so pieces land on fractional pixels, JPEG ringing,
last-move highlights, coordinate labels bleeding into edge squares, blur, and
brightness/contrast drift.
- 4,000 boards / 256,000 squares for training across 6 themes
- 600 boards / 38,400 squares for validation across 2 unseen themes
- 600 boards / 38,400 squares for test across 2 further unseen themes
**Splits are by theme, three ways.** A validation set drawn from the training
themes reports 100% and measures memorisation. One drawn from the test themes
lets epoch selection peek at the reported number. Six themes train, two select,
two are looked at once.
## Training procedure
8 epochs, AdamW with one-cycle scheduling, batch 512, label smoothing 0.02,
~22 minutes on CPU. Best epoch selected on validation board-exact match.
**Colour augmentation is the whole ballgame.** Per-channel gain, channel
permutation, random greyscale, brightness/contrast, and noise — all applied at
batch time. Every one is label-preserving because piece identity in these sprites
is carried by *luminance* (white pieces are light with a dark outline, black the
reverse), never by hue. So hue can be attacked freely, and must be.
## Evaluation
Board-level exact match is the metric that matters. A FEN wrong in one square is
wrong, and per-square accuracy hides that.
| Themes | Per-square | **Board exact** |
|---|--:|--:|
| Seen (training) | 100.0000% | 100.00% |
| Unseen (validation) | 100.0000% | 100.00% |
| **Unseen (test)** | **99.8724%** | **94.50%** |
### The augmentation ablation
`--no-augment` reproduces the failure the augmentation was written to fix:
| | Per-square (test) | **Board exact (test)** |
|---|--:|--:|
| Without augmentation | 96.1745% | **58.83%** |
| With augmentation | 99.8724% | **94.50%** |
| Δ | +3.70 pts | **+35.67 pts** |
Without it the model reached 100.0000% per-square accuracy on the six themes it
trained on and collapsed on an unfamiliar palette. It had learned colour schemes,
not chess pieces.
## Limitations
**94.5%, not 99%.** One board in eighteen is still wrong somewhere on an
unfamiliar theme. The legality repair search recovers some of those, but it can
only fix boards whose errors make the position *illegal* — a bishop misread as a
queen usually leaves a perfectly legal board and passes through silently.
**Evaluated on synthetic themes, not real screenshots.** Unseen renders are a
proxy for transfer, not a measurement of it. A hand-labelled set of real captures
from Lichess and Chess.com would be the honest test and does not exist here.
**Two held-out splits disagreed sharply.** In the ablation the validation themes
scored 99.17% board exact and the test themes 58.83% — same model, same run.
Transfer depends heavily on *which* unfamiliar theme, so 94.50% should be read as
one sample from a wide distribution rather than a guarantee.
**Assumes a square, axis-aligned, tightly-cropped board.** `autocrop` handles
uniform page background and deliberately gives up rather than guess. A skewed or
partially occluded board is out of scope and will fail without saying so.
**Piece sets.** Trained on one sprite set (the Wikipedia pieces) with geometric
and colour augmentation. A visually distinct set — Lichess's `cburnett`,
Chess.com's `neo` — is untested.
## Ethical considerations
Low risk. The model reads chessboards. It processes user-supplied images, which
are held in memory for the duration of a request and not stored; uploads are
capped at 8 MB.
---