Downloads · 30 days
10
10% of all-time downloads
octaviomartinez/trm-chess
trm-chess is a reinforcement learning model from octaviomartinez. Use it for the reinforcement learning task on the model card, and read the license before you ship it in a product. It is set up for pytorch. The card lists the license as apache-2.0.
Downloads · 30 days
10
10% of all-time downloads
All-time downloads
101
Public
Parameters
39.4M
2.7 GB on disk
Likes
3
Public
Click a slice to open those files.
.pt158 MB · 50%
From the Hugging Face model README
English below | Español más abajo
Try it live: https://huggingface.co/spaces/octaviomartinez/trm-chess
A chess engine built with an experimental architecture: TRM (Tiny Recursive Model) combined with BitNet-style ternary weights. As far as could be confirmed, this combination had never been publicly tried before in the chess domain -- TRM and its predecessor HRM (Hierarchical Reasoning Model) were originally designed for grid-based tasks like Sudoku, mazes, and ARC-AGI, not classic board games.
The core: TRM (Tiny Recursive Model). Unlike a network that sees the board once and responds, this model iterates over itself several times before deciding on a move: a recursive reasoning process with two internal states.
z: the reasoning "scratchpad", updated several times per cycley: the answer being refined, updated once per cycleBoth states are updated using the same shared network (2 transformer layers), not two separate networks -- that's the key simplification TRM introduced over HRM, which used two distinct networks for the same two functions.
Ternary weights (BitNet b1.58). The recursive core's layers quantize
their weights to only three possible values: {-1, 0, +1}, with a separate
scale factor (BitNet b1.58 style). This greatly reduces the core's
computational cost. The output heads (policy and value) stay at normal
precision, since they need to discriminate fine evaluation differences that
quantization would ruin.
Input/output representation. Board: 19 planes of 8x8 (own/opponent pieces, turn, castling rights, en passant, halfmove clock), always from the mover's perspective. Moves: 64 origin squares x 64 destination squares x 4 promotion variants = 16,384 possible moves encoded as a single index.
Parameters: ~22 million total. The recursive core itself is small (consistent with TRM's spirit); most parameters live in the policy head, whose output size (16,384 classes) is inherently large regardless of core size.
Method: Stockfish distillation. The model learned by imitating millions of real positions from the Lichess database, each with the move Stockfish considered best and its numeric evaluation -- not by playing against itself (self-play).
Lichess/chess-position-evaluations (394M total positions
available; a 12M subset filtered by Stockfish analysis depth >= 18 was used)Trained by combining free GPUs from Google Colab, Kaggle, and Lightning AI -- no dedicated or paid infrastructure.
!pip install huggingface_hub torch python-chess safetensors -q
!wget -q https://huggingface.co/octaviomartinez/trm-chess/raw/main/model_chess.py
import chess
import torch
from model_chess import TRMChess, board_to_tensor, get_legal_move_mask, index_to_move
model = TRMChess.from_pretrained("octaviomartinez/trm-chess")
model.eval()
board = chess.Board()
with torch.no_grad():
out = model(board_to_tensor(board).unsqueeze(0))
logits = out["policy_logits"].squeeze(0)
mask = get_legal_move_mask(board)
logits[~mask] = -1e9
best_move = index_to_move(logits.argmax().item(), board)
print(best_move.uci())
For real play with MCTS search (stronger than raw policy alone), see
play_chess.py in this repository.
Note on the "Use this model" widget: this repo doesn't use the standard
transformers library integration (it uses the lighter huggingface_hub
PyTorchModelHubMixin instead), so the automatic Transformers/Colab/Kaggle
tabs shown on some other model pages don't appear here. The code snippet
above works the same way -- just copy-paste it into any Python environment
(Colab, Kaggle, or local).
For actual play, the model doesn't just use its raw policy -- it's combined with Monte Carlo Tree Search (MCTS), similar in spirit to AlphaZero: candidate moves are simulated, promising lines are explored deeper guided by the network's policy, and resulting positions are evaluated with the value head.
Measured against Stockfish limited to various Elo levels (using
UCI_LimitStrength + UCI_Elo), playing real game series (not just
self-play estimation). The real result landed considerably lower than
initial self-play-based estimates, roughly 800-1200 Elo, evidencing a
known limitation of pure distillation: the model generalizes worse against
playing styles it never saw during training.
Apache 2.0.
Motor de ajedrez construido con una arquitectura experimental: TRM (Tiny Recursive Model) combinado con pesos ternarios estilo BitNet. Hasta donde se pudo confirmar, esta combinacion nunca se probo publicamente antes en el dominio del ajedrez -- TRM y su predecesor HRM (Hierarchical Reasoning Model) se disenaron originalmente para tareas de grilla como Sudoku, laberintos y ARC-AGI, no para juegos de mesa clasicos.
El nucleo: TRM (Tiny Recursive Model). A diferencia de una red que ve el tablero una vez y responde, este modelo itera sobre si mismo varias veces antes de decidir una jugada: un proceso de razonamiento recursivo con dos estados internos.
z: el "borrador" de razonamiento, se actualiza varias veces por cicloy: la respuesta que se va refinando, se actualiza una vez por cicloAmbos estados se actualizan usando la misma red compartida (2 capas transformer), no dos redes separadas -- esa es la simplificacion clave que propuso TRM sobre HRM, que usaba dos redes distintas para las mismas dos funciones.
Pesos ternarios (BitNet b1.58). Las capas del nucleo recursivo
cuantizan sus pesos a solo tres valores posibles: {-1, 0, +1}, con un
factor de escala aparte (estilo BitNet b1.58). Esto reduce mucho el costo
computacional del nucleo. Las cabezas de salida (policy y value) se
mantienen en precision normal, porque necesitan discriminar diferencias
finas de evaluacion que la cuantizacion arruinaria.
Representacion de entrada y salida. Tablero: 19 planos de 8x8 (piezas propias/rivales, turno, derechos de enroque, captura al paso, contador de jugadas sin captura), siempre desde la perspectiva del jugador que mueve. Jugadas: 64 casillas de origen x 64 de destino x 4 variantes de promocion = 16,384 jugadas posibles codificadas como un unico indice.
Parametros: ~22 millones de parametros totales. El nucleo recursivo en si es chico (consistente con el espiritu de TRM); la mayor parte de los parametros vive en la cabeza de policy, cuyo tamano de salida (16,384 clases) es inherentemente grande sin importar el tamano del nucleo.
Metodo: destilacion de Stockfish. El modelo aprendio imitando millones de posiciones reales de la base de datos de Lichess, cada una con la jugada que Stockfish considero mejor y su evaluacion numerica -- no jugando contra si mismo (self-play).
Lichess/chess-position-evaluations (394M de posiciones
totales disponibles; se uso un subconjunto de 12M filtrado por
profundidad de analisis de Stockfish >= 18)Se entreno combinando GPUs gratuitas de Google Colab, Kaggle, y Lightning AI -- sin infraestructura dedicada ni paga.
!pip install huggingface_hub torch python-chess safetensors -q
!wget -q https://huggingface.co/octaviomartinez/trm-chess/raw/main/model_chess.py
import chess
import torch
from model_chess import TRMChess, board_to_tensor, get_legal_move_mask, index_to_move
model = TRMChess.from_pretrained("octaviomartinez/trm-chess")
model.eval()
board = chess.Board()
with torch.no_grad():
out = model(board_to_tensor(board).unsqueeze(0))
logits = out["policy_logits"].squeeze(0)
mask = get_legal_move_mask(board)
logits[~mask] = -1e9
best_move = index_to_move(logits.argmax().item(), board)
print(best_move.uci())
Para jugar de verdad con busqueda MCTS (mas fuerte que solo la policy
cruda), ver play_chess.py en este mismo repositorio.
Nota sobre el panel "Use this model": este repo no usa la integracion
estandar de la libreria transformers (usa en cambio el mixin mas liviano
PyTorchModelHubMixin de huggingface_hub), asi que las pestanas
automaticas de Transformers/Colab/Kaggle que se ven en otras paginas de
modelos no aparecen aca. El codigo de arriba funciona igual -- solo hay que
copiarlo y pegarlo en cualquier entorno de Python (Colab, Kaggle, o local).
Para jugar, el modelo no usa solo su policy directamente -- se combina con una busqueda tipo Monte Carlo Tree Search (MCTS), similar en espiritu a AlphaZero: se simulan muchas jugadas candidatas, se profundiza en las lineas mas prometedoras guiado por la policy de la red, y se evaluan las posiciones resultantes con el value head.
Se midio contra Stockfish limitado a distintos niveles de Elo (usando
UCI_LimitStrength + UCI_Elo), jugando series de partidas reales (no
solo estimando por partidas contra si mismo). El resultado real quedo en
un rango bastante mas bajo que las estimaciones iniciales basadas en
partidas contra si mismo, aproximadamente 800-1200 Elo, evidenciando
una limitacion conocida de la destilacion pura: el modelo generaliza peor
contra estilos de juego que nunca vio durante el entrenamiento.
Apache 2.0.