Izzent commited on
Commit
2063f92
·
verified ·
1 Parent(s): 2dbcd95

Create README.md

Browse files
Files changed (1) hide show
  1. README.md +112 -0
README.md ADDED
@@ -0,0 +1,112 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ language: en
3
+ tags:
4
+ - chess
5
+ - transformer
6
+ - pytorch
7
+ - move-prediction
8
+ - from-to-heads
9
+ - recurrent-transformer
10
+ datasets:
11
+ - angeluriot/chess_games
12
+ metrics:
13
+ - cross-entropy
14
+ - move-accuracy
15
+ ---
16
+
17
+ # Recurrent Transformer for Chess Move Prediction (v1)
18
+
19
+ Recurrent transformer that predicts the best chess move from a board state (FEN). Trained from scratch; uses From/To square prediction heads and a shared transformer block applied 8 times with iteration embeddings (CORnet-s / Universal Transformer style). Output is always a legal move (zero fallbacks).
20
+
21
+ **Part of:** INFOMTALC 2025/26 (Utrecht University, MSc Applied Data Science) — chess tournament assignment.
22
+
23
+ ---
24
+
25
+ ## Model description
26
+
27
+ - **Architecture:** Encoder-only transformer with recurrent weight sharing. Board is encoded as 70 tokens (turn, castling×4, 64 squares, en passant) using a spatial tokenizer (14 piece IDs). Separate embeddings per token type; one shared block (multi-head self-attention + feed-forward with GELU) applied 8 times with learned iteration embeddings. Two linear heads score each of the 64 squares as source and destination; each legal move is scored as `from_logits[src] + to_logits[dst]` and the best is returned.
28
+ - **Inspiration:** From/To heads from [sgrvinod/chess-transformers](https://github.com/sgrvinod/chess-transformers); recurrent shared block from CORnet-s (Kubilius et al., 2019) and BLT networks (Spoerer et al., 2017).
29
+ - **Parameters:** ~3.2M (d_model=512, 8 heads, FFN=2048, 8 iterations).
30
+ - **Input:** FEN string.
31
+ - **Output:** Single UCI move string (e.g. `e2e4`). No sampling; deterministic given the position.
32
+
33
+ ---
34
+
35
+ ## Intended use
36
+
37
+ - **Intended:** Chess move prediction for the INFOMTALC tournament and similar setups (player that receives FEN and returns UCI move). Runs on CPU or GPU; fits on free-tier Colab (T4).
38
+ - **Not intended:** General-purpose chess engine, opening book, or strength comparable to Stockfish. This is a small transformer trained on engine labels, not a full engine.
39
+
40
+ ---
41
+
42
+ ## Training data
43
+
44
+ - **Source:** [angeluriot/chess_games](https://huggingface.co/datasets/angeluriot/chess_games) (games filtered to ELO ≥ 1500).
45
+ - **Labels:** Best move per position from local Stockfish (depth 10).
46
+ - **Size:** 750K (FEN, UCI) pairs in JSONL format.
47
+
48
+ ---
49
+
50
+ ## Training procedure
51
+
52
+ - **Loss:** Cross-entropy on from-square and to-square predictions separately.
53
+ - **Optimizer:** AdamW with Vaswani-style learning rate schedule (warmup 4000 steps).
54
+ - **Batch size:** 512.
55
+ - **Epochs:** 16 with early stopping (patience 2).
56
+ - **Hardware:** Trained locally (5070Ti). Inference runs on free-tier Colab T4.
57
+
58
+ ---
59
+
60
+ ## How to use
61
+
62
+ Requires the [chess_exam](https://github.com/bylinina/chess_exam) package (for the `Player` base class and `Game`). Install it, then use the model via the tournament player class from the assignment repo:
63
+
64
+ ```python
65
+ # Install tournament framework
66
+ # git clone https://github.com/bylinina/chess_exam.git && cd chess_exam && pip install -e .
67
+
68
+ from chess_tournament import Game, RandomPlayer
69
+ from player import TransformerPlayer # from the assignment repo that contains model.py + player.py
70
+
71
+ tp = TransformerPlayer("RecurrentTransformer") # downloads this model from HF on first use
72
+ rp = RandomPlayer("Random")
73
+ game = Game(tp, rp, max_half_moves=200)
74
+ outcome, scores, fallbacks = game.play()
75
+ print(outcome, fallbacks)
76
+ ```
77
+
78
+ **Loading only the PyTorch state dict (no player):**
79
+
80
+ ```python
81
+ import json
82
+ import torch
83
+ from huggingface_hub import hf_hub_download
84
+ from model import RecurrentTransformer # need model.py from the assignment repo
85
+
86
+ config_path = hf_hub_download("Izzent/recurrent-transformer-chess", "config.json")
87
+ weights_path = hf_hub_download("Izzent/recurrent-transformer-chess", "model.pt")
88
+
89
+ with open(config_path) as f:
90
+ config = json.load(f)
91
+
92
+ model = RecurrentTransformer.from_config(config)
93
+ state = torch.load(weights_path, map_location="cpu", weights_only=True)
94
+ model.load_state_dict(state)
95
+ model.eval()
96
+
97
+ # Forward pass expects a batch dict: board (B,64), turn (B,1), castling (B,4), ep (B,1)
98
+ # Use BoardTokenizer.encode(fen) to get these from a FEN string.
99
+ ```
100
+
101
+ ---
102
+
103
+ ## Files
104
+
105
+ - `config.json`: Model config (d_model, nhead, d_ff, num_iterations, dropout).
106
+ - `model.pt`: PyTorch state dict (weights only).
107
+
108
+ ---
109
+
110
+ ## License
111
+
112
+ All rights reserved.