Downloads · 30 days
8
44% of all-time downloads
ansarzeinulla/bestemshe-resmlp
bestemshe-resmlp is a reinforcement learning model from ansarzeinulla. 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 mit.
Authors: Ansar Zeinulla & Murat Manassov · Nazarbayev University Oracle (tablebase): ansarzeinulla/bestemshe-tablebase (8.3 GiB, 1.26×10¹¹ positions) Code: github.com/ansarzeinulla/Bestemshe
Downloads · 30 days
8
44% of all-time downloads
All-time downloads
18
Public
Parameters
17.2M
482 MB on disk
Likes
1
Public
Click a slice to open those files.
.pt207 MB · 75%
From the Hugging Face model README
Authors: Ansar Zeinulla & Murat Manassov · Nazarbayev University Oracle (tablebase): ansarzeinulla/bestemshe-tablebase (8.3 GiB, 1.26×10¹¹ positions) Code: github.com/ansarzeinulla/Bestemshe
A dual-headed residual MLP trained by supervised distillation on positions labelled by the exact Bestemshe tablebase. It predicts, for the side to move:
| File | Content | Size |
|---|---|---|
model.safetensors + config.json | weights only (recommended) | 69 MB |
latest.pt | full training checkpoint: weights, optimizer state, args, step | 207 MB |
Both hold the same weights: outputs are identical.
1024 → 3, policy 1024 → 5.| Metric | Value |
|---|---|
| Value-preserving moves | 99.69% (226,232 of 226,933; 701 value-losing moves) |
| Games ending below the theoretical result | 556 of 2,000 (27.8%) = 556 of the 1,036 games the model started won or drawn (53.7%) |
| Average model moves per game | 113 |
| Random-move baseline (other starts, 100 games) | 97.48% value-preserving moves |
Deeper search helps:
A same-start comparison of all move-selection methods is being run with the updated evaluation/vs_god.py.
| Metric | Value |
|---|---|
| Accuracy (argmax WDL) | 85.7% |
| Expected calibration error (15 bins) | 0.0098 |
| Mean confidence when wrong / right | 0.673 / 0.891 |
| Draw recall | 0 (146 true draws; draw is never the argmax) |
A telling example: on the initial position the value head gives the first player win 0.89 / draw 0.05 / loss 0.06. The tablebase says it is a loss (the second player wins).
Errors concentrate where a position's latent neighbours carry other labels: 0% error in the most homogeneous 30% of positions, 80% in the most mixed decile. Script: analysis/latent_calibration.py.
A cheap greedy 1-ply check on uniformly sampled positions, run at each checkpoint, rose to 97.0% value-preserving moves and 92.9% value accuracy at the final step. Full history: the eval_results_*.json files of the training run.
pip install torch safetensors huggingface_hub
import json, torch, torch.nn as nn, torch.nn.functional as F
from huggingface_hub import hf_hub_download
from safetensors.torch import load_file
class ResBlock(nn.Module):
def __init__(self, w):
super().__init__()
self.norm, self.fc1, self.fc2 = nn.LayerNorm(w), nn.Linear(w, w), nn.Linear(w, w)
def forward(self, x):
return x + self.fc2(F.gelu(self.fc1(self.norm(x))))
class BestemsheNet(nn.Module):
def __init__(self, width=1024, blocks=8, emb=32):
super().__init__()
self.pit_emb, self.kaz_emb = nn.Embedding(51, emb), nn.Embedding(13, emb)
self.inp = nn.Linear(12 * emb, width)
self.body = nn.Sequential(*[ResBlock(width) for _ in range(blocks)])
self.value_head, self.policy_head = nn.Linear(width, 3), nn.Linear(width, 5)
def forward(self, pits, kaz):
x = torch.cat([self.pit_emb(pits).flatten(1), self.kaz_emb(kaz).flatten(1)], dim=1)
h = self.body(F.gelu(self.inp(x)))
return self.value_head(h), self.policy_head(h)
repo = "ansarzeinulla/bestemshe-resmlp"
cfg = json.load(open(hf_hub_download(repo, "config.json")))
model = BestemsheNet(cfg["width"], cfg["blocks"]).eval()
model.load_state_dict(load_file(hf_hub_download(repo, "model.safetensors")))
# side to move: pits[0:5] own, pits[5:10] opponent; kazans are even, passed as kazan // 2
pits = torch.tensor([[5] * 10]); kaz = torch.tensor([[0, 0]])
with torch.no_grad():
value, policy = model(pits, kaz)
print(dict(zip(["loss", "draw", "win"], torch.softmax(value, 1)[0].tolist())))
@misc{zeinulla2026bestemshe_model,
title = {Bestemshe ResMLP: Value and Policy Distillation from an Exact Oracle},
author = {Zeinulla, Ansar and Manassov, Murat},
year = {2026},
publisher = {Hugging Face},
howpublished = {\url{https://huggingface.co/ansarzeinulla/bestemshe-resmlp}}
}