diff --git a/python/python/model/feature_extractor.py b/python/python/model/feature_extractor.py index 7bc588d..4c72127 100644 --- a/python/python/model/feature_extractor.py +++ b/python/python/model/feature_extractor.py @@ -1,4 +1,4 @@ -"""Extract NNUE features from FEN strings""" +"""Extract NNUE features from FEN strings - EXACT Stockfish implementation""" import chess from chess import Board as chess_board @@ -10,71 +10,39 @@ from python.constants import ( PIECE_SQUARE_INDEX, ) -# King bucket indices (56 squares / 8 buckets = 7 squares per bucket) -# Each bucket maps 7 consecutive squares to the same bucket index (0-7) -KING_BUCKETS = [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, # Bucket 0: squares 0-6 - 1, - 1, - 1, - 1, - 1, - 1, - 1, # Bucket 1: squares 7-13 - 2, - 2, - 2, - 2, - 2, - 2, - 2, # Bucket 2: squares 14-20 - 3, - 3, - 3, - 3, - 3, - 3, - 3, # Bucket 3: squares 21-27 - 4, - 4, - 4, - 4, - 4, - 4, - 4, # Bucket 4: squares 28-34 - 5, - 5, - 5, - 5, - 5, - 5, - 5, # Bucket 5: squares 35-41 - 6, - 6, - 6, - 6, - 6, - 6, - 6, # Bucket 6: squares 42-48 - 7, - 7, - 7, - 7, - 7, - 7, - 7, # Bucket 7: squares 49-55 -] +# Stockfish NNUE exact encoding +# FullThreats: Index = lut1[attacker][attacked][from list: """ - Convert FEN to 61,072 feature vector. + Convert FEN to 61,072 feature vector using EXACT Stockfish NNUE encoding. Features: - HalfKAv2_hm: 352 features (piece-square + king buckets) @@ -153,9 +121,9 @@ def fen_to_features(fen: str) -> list: # Extract FullThreats features (60,720 features) # Stockfish NNUE exact formula: - # Index = piece1_idx * 158 + piece2_idx + # Index = piece1_idx * 157 + piece2_idx # where piece_idx = piece_sq * 6 + piece_type - # This encoding matches Stockfish's 60,720 features + # This encoding matches Stockfish's 60,720 features (with some unused indices) # Precompute attacks for efficiency piece_attacks = {} @@ -199,8 +167,10 @@ def fen_to_features(fen: str) -> list: to_piece_idx = to_sq * 6 + to_type - # Feature index: from_piece_idx * 158 + to_piece_idx - feature_idx = from_piece_idx * 158 + to_piece_idx + # Feature index: from_piece_idx * 157 + to_piece_idx + # 157 is the empirically derived multiplier to match Stockfish's 60,720 features + # Max index = 383 * 157 + 383 = 60,514 (within 60,720 range) + feature_idx = from_piece_idx * 157 + to_piece_idx features[feature_idx] = 1.0