RDTChess / predict.py
RDTvlokip's picture
renommer les poids en RDTChess.pt
04d8212 verified
Raw
History Blame Contribute Delete
2.46 kB
"""Pick a move with the released network. One forward pass, no search.
python predict.py # from the initial position
python predict.py "FEN ..." # from any FEN
The three steps that matter, and the order they go in:
1. encode the board in the **canonical frame** -- the side to move is always
"white, playing up the board", so a position and its colour-reversed twin
share one representation;
2. read the policy logits **only at the legal move indices**, because the head
emits all 4096 from/to pairs and roughly 99% of them are illegal here;
3. softmax over that short list, not over the 4096.
Skipping step 2 is the usual way to get nonsense out of this model.
"""
import sys
import chess
import numpy as np
import torch
from encoding import board_to_planes, legal_move_indices
from network import ChessNetwork
CHECKPOINT = "RDTChess.pt"
@torch.no_grad()
def evaluate(model: ChessNetwork, board: chess.Board, device: str = "cpu"):
"""Return the legal moves, their probabilities, and the value of `board`.
`value` is in [-1, 1] and always answers "how good is this for the side to
move", which is what the canonical frame buys.
"""
moves, indices = legal_move_indices(board)
if not moves:
return [], np.empty(0), 0.0
planes = torch.from_numpy(board_to_planes(board)).unsqueeze(0).to(device)
logits, value = model(planes)
legal = logits[0, torch.as_tensor(indices.astype(np.int64), device=device)]
probabilities = torch.softmax(legal.float(), dim=0).cpu().numpy()
return moves, probabilities, float(value.item())
def main() -> int:
board = chess.Board(sys.argv[1]) if len(sys.argv) > 1 else chess.Board()
device = "cuda" if torch.cuda.is_available() else "cpu"
model = ChessNetwork.from_checkpoint(CHECKPOINT, device=device)
moves, probabilities, value = evaluate(model, board, device)
if not moves:
print("no legal move -- the game is over")
return 0
order = np.argsort(-probabilities)
print(board)
print(f"\n{'white' if board.turn else 'black'} to move")
print(f"value {value:+.3f} (positive favours the side to move)\n")
print("top 5 moves")
for rank in order[:5]:
print(f" {board.san(moves[rank]):8s} {probabilities[rank] * 100:5.1f} %")
print(f"\nplayed: {board.san(moves[order[0]])}")
return 0
if __name__ == "__main__":
raise SystemExit(main())