前回試した軽量価値ネットワークをStockfishの探索に組み込むことを検討している。
最終的には、dlshogiのMCTSベースの探索とStockfishベースの探索を組み合わせることを構想しているが、まずは、単体で動作するStockfishベースのプログラムを作りたい。
実装方針
今後、dlshogiの探索と組み合わせる際に、効率的に組み合わせるには、一つのプログラムで局面の情報を共有したいため、現在のAperyベースのdlshogiの局面管理(Positionクラス)や、指し手生成(MoveListクラス)などは、共通化したい。
既存のPositionやMoveListなどは、Stockfishの探索部にそのまま適用することができない部分があるため、接合する仕組みが必要になる。
その方法として、以下の案を考えた。
1. 既存のクラスをStockfishベースに置き換える
2. まったく別に作成して、情報を受け渡す際の変換処理を実装する
3. 既存のクラスを継承して、不足部分と置換する部分のみを開発する
1.は、今後Stockfishのソースを流用しやすくなるメリットがあるが、将棋特有の処理を一から実装する必要があり、既存のdlshogiにも影響するので、作業量が多い。
2.は、既存のdlshogiには影響しないが、やはり将棋特有の処理を実装するのが大変である。
3.は、不足部分と置換する部分のみを開発すれば良く、既存のdlshogiへの影響も小さい。
作業量を優先して、3.の方法で実装することにする。
既存のクラス・構造体を継承して実装する場合、既存のクラス・構造体のメモリ配置は変えられないため、既存のクラス・構造体に一部フィールドを追加することになる。
dlshogi側のメモリ消費が無駄に増えるため、できれば影響がない方法で実装したいが、いったん気にせず後で考えることにする。
既存のクラス継承したクラス
Stockfishの名前空間で、既存のクラスを継承して同名のクラスを定義する。
いったん継承しただけのクラスを定義して、Stockfishから流用した探索の処理で、コンパイルエラーになる箇所について、追加実装する。
名前のみの違いの場合は、Stockfishのコードを修正しないで良いように、別名で定義し直す。
追加で必要なメソッドは追加で実装する。
Positionクラスの例:
class Position : public ::Position { ... // Doing and undoing moves void do_move(Move m, StateInfo& newSt) { doMove(m, newSt); } // 名前変換 void undo_move(Move m) { undoMove(m); } // 名前変換 void do_null_move(StateInfo& newSt, const TranspositionTable& tt); // 追加実装 void undo_null_move(); // 追加実装 // Static Exchange Evaluation bool see_ge(Move m, int threshold = 0) const; // 追加実装 ... };
Stockfishのコード流用
Stockfishのコードをコピーして、既存クラスから継承したクラスに置き換えたことで、コンパイルエラーになる箇所を修正する。
また、チェス固有の処理を将棋固有の処理に置き換える。
推論処理
前回試した軽量の畳み込みニューラルネットワークの推論を効率的に探索に組み込には、NNUEのように入力層の差分更新を行おうとすると、実装が大変になる。
いったん、差分更新は実装しないで、毎回特徴量を作成して、入力層を計算することにする。
入力層はEmbeddingを使うので、辞書引きと加算なので、そこまで遅くはならない見込みである。
推論処理は、いったんLibTorchを使って独自実装を省くことにする。
CPUで高速に推論するには量子化が必要なため、PyTorchで量子化認識トレーニングで量子化する。
torch.compileでモデルを最適化して、MKLをバックエンドに使えば、独自実装するよりも速い可能性もあるが、パフォーマンスがでなければ後で考える。
実装
実装に着手したが、1日、2日では終わらない作業量である。
将棋固有の処理は、やねうら王の実装も参考にしながら実装している。
実装中に、やねうら王のバグを見つけて、PRを上げた。
最下位ビット以外が1になる場合があるバグ修正 by TadaoYamaoka · Pull Request #297 · yaneurao/YaneuraOu · GitHub
SEE (Static Exchange Evaluation)の処理で、連続した駒の交換を評価する際に、桂馬の交換時に2枚以上の桂馬の効きがあると1つしか考慮されない場合があるというバグである。
PRマージ後に、やねうらお氏が計測したところ、頻度が少ないため棋力にはほぼ影響はなかったようである。
まとめ
軽量価値ネットワークをStockfishの探索に組み込むために、Stockfishベース探索の実装を始めた。
最小限の作業量でいったん完成させるつもりだが、それでもまだ時間はかかりそうである。
Stockfishの探索について理解を深めたいという目的もあるので、実装しながら理解していくつもりである。