Datdanboi25 commited on
Commit
4aae174
·
verified ·
1 Parent(s): 2f501a4

Update Readme

Browse files
Files changed (2) hide show
  1. .gitignore +1 -0
  2. README.md +69 -35
.gitignore ADDED
@@ -0,0 +1 @@
 
 
1
+ convert_checkpoint.py
README.md CHANGED
@@ -1,46 +1,80 @@
1
- # Chess Transition Policy
 
 
 
 
2
 
3
  ## Architecture
4
 
5
- Chess move-ranking model with 32,537,088 parameters. It receives a current
6
- board and every legal successor board, then returns one score per candidate.
7
- Legal move generation remains outside the model.
8
-
9
- - Board input: `[B, 64]` mover-relative piece IDs (`0`–`12`), with Black
10
- positions rank-flipped using `square ^ 56`.
11
- - Board encoder: piece and square embeddings, learned summary token, and 6
12
- fully bidirectional transformer layers.
13
- - Move representation: `encoded_successor - encoded_current`.
14
- - Candidate encoder: current board plus move transitions, 12 fully
15
- bidirectional transformer layers, and board/move type embeddings.
16
- - Hidden size: 384; attention heads: 6; head dimension: 64.
17
- - Feed-forward: SwiGLU with hidden size 1,040.
18
- - Scoring: RMS-normalized query/key projections and scaled dot product.
19
- - Output: `logits[B, M]`, preserving the caller’s legal-move order; padded
20
- candidates are `-inf`.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
 
22
  ## Training
23
 
24
- The model was trained on chess positions from tournament games using legal
25
- successor boards generated with `python-chess`. Training used supervised move
26
- targets and optional Stockfish teacher-logit distillation.
27
 
28
- - Optimizer: AdamW.
29
- - Precision: BF16 autocast on supported CUDA hardware.
30
- - Attention: PyTorch scaled-dot-product attention, fully bidirectional.
31
- - Dropout: 0.0 by default.
32
- - Checkpoints contain model weights, optimizer/scheduler state, training step,
33
- and architecture configuration.
34
 
35
- Convert a project checkpoint with:
36
 
37
- ```powershell
38
- python convert_checkpoint.py --checkpoint ../../checkpoints/policy/on-policy/step-0006000.pt
39
- ```
40
 
41
- The published weights in this folder are from the on-policy step-6000
42
- checkpoint:
43
 
44
- ```text
45
- ../../checkpoints/policy/on-policy/step-0006000.pt
46
- ```
 
 
1
+ # Charles the Chess Bot
2
+
3
+ This is Charles, a bot designed by me for [EnderChef's](https://huggingface.co/Enderchef) chess model competition. Charles moves quickly and does not search deeply; it chooses the move that best matches the current board according to its learned policy.
4
+
5
+ I describe Charles' architecture as zero-shot as after hearing about the competition, I came up with the whole thing while walking home in around 20 minutes, without looking at any other engine architectures. There were no iterations during training, so the model has clear design limitations.
6
 
7
  ## Architecture
8
 
9
+ Charles contains 32,537,088 parameters and consists of two primary parts: the Board Encoder and the Move Decider. The data flow is:
10
+
11
+ 1. The Board Encoder encodes the current board state.
12
+ 2. The Board Encoder encodes the board state after every legal move.
13
+ 3. Move embeddings are created by subtracting the current board embedding from the corresponding successor-board embedding. This produces one transition embedding per legal move, typically around 20.
14
+ 4. The original current-board embedding is preserved unchanged as the fixed scoring query.
15
+ 5. A copy of the current-board embedding is prepended to the move embeddings and passed through the Move Decider.
16
+ 6. The Move Decider contextualizes the copied board token and all move tokens using bidirectional attention.
17
+ 7. The contextualized move embeddings are projected through a learned, bias-free key matrix.
18
+ 8. The original, unaltered current-board embedding is projected through a learned, bias-free query matrix.
19
+ 9. Query and key vectors are RMS-normalized and compared with scaled dot products to produce one logit per legal move.
20
+ 10. The highest-scoring legal move is selected greedily.
21
+
22
+ ### Board Encoder
23
+
24
+ | Component | Details |
25
+ |---|---|
26
+ | Input | Tokenized board `[64]` |
27
+ | Piece vocabulary | 13 IDs: empty, mover pieces, opponent pieces |
28
+ | Piece embedding | `13 x 384` |
29
+ | Square embedding | Learned absolute `64 x 384` embeddings |
30
+ | Board tokens | Piece embedding + square embedding |
31
+ | Summary token | Learned `384`-dimensional token prepended |
32
+ | Transformer | 6 bidirectional transformer layers |
33
+ | Attention | 6 heads, 64 dimensions per head |
34
+ | Feed-forward | SwiGLU, hidden size 1,040 |
35
+ | Output | One `384`-dimensional board embedding |
36
+ | Causal masking | None |
37
+
38
+ ### Move Decider
39
+
40
+ | Component | Details |
41
+ |---|---|
42
+ | Current board | Encoded once by the Board Encoder |
43
+ | Successor boards | Encoded once per legal move |
44
+ | Move embeddings | `successor_embedding - current_embedding` |
45
+ | Candidate count | Typically around 20 legal moves |
46
+ | Candidate sequence | Current board copy + all move embeddings |
47
+ | Type embeddings | Separate board-token and move-token embeddings |
48
+ | Candidate positions | No candidate position embeddings |
49
+ | Transformer | 12 bidirectional transformer layers |
50
+ | Attention | 6 heads, 64 dimensions per head |
51
+ | Feed-forward | SwiGLU, hidden size 1,040 |
52
+ | Query source | Original, unaltered current-board embedding |
53
+ | Query projection | Bias-free `384 x 384` linear layer |
54
+ | Key source | Contextualized move embeddings |
55
+ | Key projection | Bias-free `384 x 384` linear layer |
56
+ | Normalization | Parameter-free RMSNorm on queries and keys |
57
+ | Scoring | Scaled query-key dot product |
58
+ | Output | One logit per legal move |
59
+ | Padding | Invalid candidates masked to `-inf` |
60
 
61
  ## Training
62
 
63
+ The model was trained in three phases on tournament chess positions. Legal moves and successor boards were generated with `python-chess`.
 
 
64
 
65
+ | Phase | Data and process | Objective and details | Approx. Elo |
66
+ |---|---|---|---|
67
+ | 1. Supervised policy | Human tournament positions; the recorded human move is the target | Cross-entropy over all legal moves. AdamW; learning rate `4e-4 -> 3e-5`; 2,000-step warmup; batch size 32; gradient accumulation 4; BF16 autocast; 0.0 dropout | 1300-1400 |
68
+ | 2. Stockfish distillation | The same positions annotated with Stockfish scores for every legal move | KL distillation against the full Stockfish move distribution. Stockfish depth 12; teacher temperature 30; student temperature 1.0; fine-tuned from Phase 1 | 1700-1800 |
69
+ | 3. On-policy training | The model generates fresh games while Stockfish plays the opponent; completed rollouts are used once | For the move selected by the model, minimize `(model_probability - Stockfish_probability) ** 2`. Unchosen moves receive no direct loss. Muon for matrix weights plus AdamW for other parameters; Opponent depth 8; Teacher depth 10; 10,000-step schedule | ~2000 |
 
70
 
71
+ All phases use fully bidirectional scaled-dot-product attention. Phase 3 keeps the model's own actions rather than replacing them with Stockfish's best move, so the rollout distribution remains on-policy.
72
 
73
+ ## Changes
 
 
74
 
75
+ Changes id make if I had the time to iterate include:
 
76
 
77
+ - Static + RoPE Square embeddings: As squares both have absolute identities and relative identities
78
+ - Replace move subtraction: I reckon a linear subtraction is a rich enough transform for this task
79
+ - More Capacity: Since this Charles relies on alot of emergent properties such as next move planning and overall generalization, more capacity would almost certainly help
80
+ - Self Play: This was originally planned but ran out of time