Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

NumPy 連携(rsshogi.numpy)

rsshogi.numpy は機械学習や探索データの入出力向けに、YaneuraOu 系の PackedSfen / PackedSfenValue(PSV)および Apery / cshogi 系の HuffmanCodedPos(HCP)/ HuffmanCodedPosAndEval(HCPE)に対応する NumPy 構造化 dtype を提供する。

from rsshogi.numpy import (
    HuffmanCodedPos,
    HuffmanCodedPosAndEval,
    PackedSfen,
    PackedSfenValue,
)

このモジュールをインポートするには環境に numpy がインストールされている必要がある。

python -m pip install rsshogi numpy

構造化 dtype 一覧

dtype 定数1 要素のバイト数対応する Board / Record メソッド用途
PackedSfen32 バイトBoard.to_packed_sfen() / Board.set_packed_sfen()圧縮された局面データの格納。
PackedSfenValue40 バイトBoard.to_psv() / Record.to_psv()やねうら王形式の教師データ(PSV)の読み書き。
HuffmanCodedPos32 バイトBoard.to_hcp() / Board.set_hcp()Apery / cshogi 互換のハフマン符号化局面の格納。
HuffmanCodedPosAndEval38 バイトBoard.to_hcpe()Apery / cshogi 互換の教師データ(HCPE)の読み書き。

PackedSfen

フィールド名NumPy 型オフセット説明
sfenuint8[32]0..3232 バイトの圧縮局面データ。

PackedSfenValue

フィールド名NumPy 型オフセット説明
sfenuint8[32]0..3232 バイトの圧縮局面データ。
scoreint1632..34手番側視点の評価値(センチポーン)。
moveuint1634..3616 ビットの指し手値(Move.value)。
game_plyuint1636..38初期局面からの手数。
game_resultint838..39対局結果コード(GameResult.value)。
paddinguint839..40アライメント用パディング(0)。

HuffmanCodedPos

フィールド名NumPy 型オフセット説明
hcpuint8[32]0..3232 バイトのハフマン符号化局面データ。

HuffmanCodedPosAndEval

フィールド名NumPy 型オフセット説明
hcpuint8[32]0..3232 バイトのハフマン符号化局面データ。
evalint1632..34手番側視点の評価値(センチポーン)。
bestMove16uint1634..36Apery 形式の 16 ビット指し手値(AperyMove.value)。
gameResultint836..37勝敗結果コード(0:引き分け、1:先手勝ち、2:後手勝ち)。
dummyuint837..38アライメント用パディング(0)。

使用例

Board から構造化 ndarray へのインプレース書き込み

Board.to_packed_sfen()、to_psv()、to_hcp()、to_hcpe() の out 引数には、要素数 1 の構造化 ndarray(shape (1,))だけでなく、配列の 0 次元スライス(arr[i])を直接渡すことができる。 同様に、set_packed_sfen() と set_hcp() にも arr[i] や arr[i]["sfen"]、arr[i]["hcp"] を直接渡せる。

import numpy as np
from rsshogi.core import Board
from rsshogi.numpy import HuffmanCodedPosAndEval, PackedSfenValue
from rsshogi.record import GameResult

board = Board()
usi_moves = ["7g7f", "3c3d", "2g2f", "4c4d"]
scores = [25, -20, 35, -15]

psv_data = np.zeros(len(usi_moves), dtype=PackedSfenValue)
hcpe_data = np.zeros(len(usi_moves), dtype=HuffmanCodedPosAndEval)

for i, (usi, score) in enumerate(zip(usi_moves, scores)):
    # 0 次元スライス psv_data[i] / hcpe_data[i] へ直接書き込む
    board.to_psv(
        mv=usi,
        score=score,
        game_result=GameResult.BLACK_WIN,
        out=psv_data[i],
    )
    board.to_hcpe(
        best_move=usi,
        score=score,
        game_result=GameResult.BLACK_WIN,
        out=hcpe_data[i],
    )
    board.apply_usi(usi)

print(psv_data["score"].tolist())  # => [25, -20, 35, -15]
print(hcpe_data["eval"].tolist())  # => [25, -20, 35, -15]

バイナリ教師データファイル(.psv / .hcpe)の読み書き

import numpy as np
from rsshogi.core import AperyMove, Board, Move
from rsshogi.numpy import HuffmanCodedPosAndEval, PackedSfenValue

# 1. Record.to_psv() から NumPy 配列を構築してファイルへ保存する
from rsshogi.record import Record

record = Record.from_usi_main_line(
    "startpos",
    ["7g7f", "3c3d"],
    evals=[30, -25],
    result="BLACK_WIN",
)
psv_bytes = b"".join(record.to_psv())
psv_array = np.frombuffer(psv_bytes, dtype=PackedSfenValue)
psv_array.tofile("train.psv")

# 2. 保存した PSV ファイルを読み込んで盤面と指し手を復元する
loaded_psv = np.fromfile("train.psv", dtype=PackedSfenValue)
board = Board()
board.set_packed_sfen(loaded_psv[0])
mv = Move(int(loaded_psv[0]["move"]))
print(board.to_sfen(), mv.to_usi(), int(loaded_psv[0]["score"]))

# 3. HCPE 要素から盤面と AperyMove を復元する
hcpe_array = np.zeros(1, dtype=HuffmanCodedPosAndEval)
board.to_hcpe(best_move="7g7f", score=40, game_result=1, out=hcpe_array[0])

board.set_hcp(hcpe_array[0], game_ply=1)
apery_mv = AperyMove(int(hcpe_array[0]["bestMove16"]))
print(apery_mv.to_usi())  # => "7g7f"

関連項目