TadaoYamaokaの開発日記

個人開発しているスマホアプリや将棋AIの開発ネタを中心に書いていきます。

棋力計測の戦型分類

floodgateの戦型分類の記事にコメントをいただいたので、棋力測定時の戦型について分類してみた。

棋力測定の方法

dlshogiの棋力測定は、平手開始局面から序盤ランダムありで測定を行っている。
また、基準ソフトとして水匠5を互角になる条件に調整して、リーグ戦で対局している。

dlshogiの序盤にランダム性を加えるのは、dlshogi同士の対局で同じ棋譜になるのを防ぐためである。
ランダムの条件は、32手まで評価値(勝率)が2.5%の範囲をランダムに選択する。
評価値(勝率)の範囲は1手ごとに0.1%小さくする。

cshogi.cliのコマンド例
python -u -m cshogi.cli /work/DeepLearningShogi/usi/bin/usi /work/DeepLearningShogi/usi/bin/usi /work/YaneuraOu/bin/YaneuraOu-by-gcc --name1 pre33 --name2 pre39 --name3 suisho5-16thx5000 --options1 Const_Playout:50000,Random_Ply:32,Random_Cutoff:25,Random_Cutoff_Drop:1,PV_Mate_Search_Threads:1,C_init:127,C_base:27126,C_fpu_reduction:31,C_init_root:112,C_base_root:33311,Softmax_Temperature:140,Draw_Ply:320,UCT_NodeLimit:50000000,OwnBook:false,PV_Interval:0,DNN_Model:/work/model/model-pre33_resnet30x384_relu_b4096lr004-012.onnx,UCT_Threads:2 --options2 Const_Playout:50000,Random_Ply:32,Random_Cutoff:25,Random_Cutoff_Drop:1,PV_Mate_Search_Threads:1,C_init:127,C_base:27126,C_fpu_reduction:31,C_init_root:112,C_base_root:33311,Softmax_Temperature:140,Draw_Ply:320,UCT_NodeLimit:50000000,OwnBook:false,PV_Interval:0,DNN_Model:/work/model/model-pre39_resnet30x384_relu_b4096lr004-013.onnx,UCT_Threads:2 --options3 NodesLimit:250000000,FV_SCALE:24,USI_Hash:10240,Threads:16,PvInterval:9999,ResignValue:10000,MaxMovesToDraw:320,NetworkDelay2:0 --opening-moves 100 --draw 320 --games 1000 --pgn 20230109_pre33_vs_pre39_po50k.pgn --csa csa/csa-20230109-pre33vspre39-rnd/po50k

戦型分類

dlshogi同士と、dlshogiと水匠5それぞれで、上位10個の戦型を分類した結果は以下の通り。

pre39とpre33がdlshogi(1GPU、2スレッド)の異なるバージョン、
suisho5が、探索ノード数をdlshogiの5000倍にした水匠5(16スレッド)である。

青の棒グラフは出現率、オレンジの線グラフ(右軸)が先手勝率を示す。


考察

dlshogi同士の対局では、角換わりが40%程度、相掛かりが20%程度になっている。

dlshogiと水匠5では、dlshogiが先手の場合は、角換わり45%程度、相掛かりが20%程度になっている。
dlshogiが後手の場合は、相掛かりが25%程度、角換わりが15%程度になっている。先手腰掛銀も12%程度ある。
水匠5が先手の場合、戦型がよりばらけるようである。

指し手を学習した場合

現在、dlshogiは、指し手ではなく訪問回数の分布を学習している。
エクスプロイターの学習では、指し手を学習している。
指し手を学習した場合、ランダムでの手がばらつきが少なくなることが予想できるため、戦型を確認してみた。

エクスプロイターが先手の場合、角換わりが55%程度、相掛かりが15%程度になっている。
訪問回数の分布を学習したdlshogi同士の対局よりも、戦型のばらつきが少なくなっている。

エクスプロイターが後手の場合は、dlshogi同士の対局と同じくらいである。


同じランダムの条件でも、指し手を学習したモデルは、ランダム性が少なくなるため、見かけ上勝率が高くなるため、棋力測定としては適切ではなさそうである。
モデルの質が異なる場合は、ランダムなしで互角局面集を使用して測定した方がよい。

まとめ

dlshogiの棋力測定時の戦型について調査した。
dlshogi同士の対局では、floodgateの戦型の割合に比較的近い値になった。
水匠5が先手の場合は、より戦型がばらけていることがわかった。

また、指し手を学習したモデルは、訪問回数の分布を学習したモデルに比べてランダム性が低くなることがわかった。
モデルの質が異なる場合は、ランダムなしで互角局面集を使用して測定した方がよさそうである。

水匠の定跡作成プログラム

第3回電竜戦の水匠の定跡作成プログラムと同様のプログラムを作成した。
DeepLearningShogi/make_book_minmax.py at master · TadaoYamaoka/DeepLearningShogi · GitHub

方式

水匠の定跡作成プログラムと同様に、末端局面(一定の対局数以上の局面)の勝率をMin-Maxで開始局面に伝播させて定跡を作成する。
このプログラムは定跡作成のみ行う。
連続対局はcshogi.cliで行い、cshogi.cliで生成したCSAファイルを元に定跡を作成する。

連続対局と定跡作成は、以下のようなシェルで自動化する。

kgr0.sh
#!/bin/sh
id=$1
nodes=$2
side=$3
th=$4
python -m dlshogi.utils.make_book_minmax /work/pgn/csa /work/YaneuraOu/bin/book${id}/user_book1.db --side ${side} --startsfen "lr5nl/3g1kg2/2n1ppsp1/p1pps1p1p/1p5P1/P1PPSPP1P/1PS1P1N2/2GK1G3/LN5RL w Bb 38" --th ${th}
for ((i=0; i < 10000; i++))
do
    python3 -u -m cshogi.cli /work/YaneuraOu/bin/YaneuraOu-by-gcc /work/YaneuraOu/bin/YaneuraOu-by-gcc --name1 suisho5-4th-1 --name2 suisho5-4th-2 --options1 NodesLimit:${nodes},FV_SCALE:24,USI_Hash:4096,Threads:4,PvInterval:9999,ResignValue:500,MaxMovesToDraw:320,NetworkDelay2:0,USI_OwnBook:true,BookDir:book${id},BookFile:user_book1.db,BookMoves:256,BookEvalDiff:0,BookEvalBlackLimit:-200,BookEvalWhiteLimit:-200,BookDepthLimit:0 --options2 NodesLimit:${nodes},FV_SCALE:24,USI_Hash:4096,Threads:4,PvInterval:9999,ResignValue:500,MaxMovesToDraw:320,NetworkDelay2:0,USI_OwnBook:true,BookDir:book${id},BookFile:user_book1.db,BookMoves:256,BookEvalDiff:0,BookEvalBlackLimit:-200,BookEvalWhiteLimit:-200,BookDepthLimit:0 --opening /work/opening/kgr0.sfen --opening-moves 100 --draw 320 --games 20 --pgn 20230105_suisho5-4th-1_vs_suisho5-4th-2_nodes${nodes}-${i}.pgn --csa csa/csa-20230105-s5vss5-kgr0/nodes${nodes} > log_20230105_suisho5-4th-1_vs_suisho5-4th-2_nodes${nodes}-${i}.txt
    python -m dlshogi.utils.make_book_minmax /work/pgn/csa /work/YaneuraOu/bin/book${id}/user_book1.db --side ${side} --startsfen "lr5nl/3g1kg2/2n1ppsp1/p1pps1p1p/1p5P1/P1PPSPP1P/1PS1P1N2/2GK1G3/LN5RL w Bb 38" --th ${th}
done

連続対局の開始局面は、角換わりの37手目基本図にする(/work/opening/kgr0.sfenに定義している)。

シェル実行例
./kgr0.sh 1 100000000 black 100 &
./kgr0.sh 2 100000000 white 50 &

水匠の定跡作成では、先手番の定跡と後手番の定跡を交互作成しているが、同時並行でも問題ないので、並列で実行する。
上記例では、先手と後手を1多重にしているが、CPUコア数の分だけ多重に実行できる。
その際、同じ棋譜が生成されないように、ノード数を少しばらけさせるとよさそうである。

考察

メリット
  • 末端局面の勝率を元にしているため、途中で評価が正しくない手順があったとしても、その先の局面で反省した場合は、定跡に反映することができる。
  • 先手番もしくは後手番のその時点の定跡を幹として、その周辺の枝を伸ばすため、効率よく探索できる。
デメリット
  • 末端局面の評価は、勝率を元にしているため、対局数が十分でない場合は誤差が大きくなる。ただし、作成に十分に時間をかければ末端局面が優劣がはっきりした局面になってくるので、対局数が少なくても誤差の影響は小さくなる。
  • 連続対局の勝率を元にするため、作成に時間がかかる。角換わりの37手目基本図など、変化の狭い局面を開始局面にしないと現実的な時間では長手数の定跡は作成できない。
  • 定跡を幹として分岐する枝は、連続対局で現れた手に限られるため、連続対局に使うソフトが指さない手に好手があると、この定跡作成方法ではカバーできない。

まとめ

第3回電竜戦の水匠の定跡作成プログラムと同様のプログラムを作成した。
現在、水匠5を使って試しに定跡を作成している。
水匠電竜の定跡が今後公開されることがあれば、比較してみたい。

中盤互角局面集

先日、dlshogiと水匠が互角になる探索ノード数を調べたが、初手開始局面からdlshogiはランダムありで測定していた。
初手開始局面からだと、dlshogiは序盤で優勢を築いてそのまま勝つ場合が多いため、中終盤の精度が測定できていない可能性がある。
そこで、中盤の互角局面集を作成することにした。

以前の互角局面集

以前に互角局面集を作成したが、これはfloodgateの棋譜を使って、24手目から36手目までが評価値±100以内という条件で作成している。
24手目から開始することを想定して作成している。
読みが重要になる中盤よりも前の局面になっているため、今回は読みが重要な局面を抽出したい。

作成条件

中盤の読みが重要になる少し前の局面を抽出するために、以下の条件とした。

  • R3800以上同士の対局のみ
  • 投了、千日手入玉宣言勝ち、持将棋で終局している
  • 50手未満の棋譜は除外
  • どちらかに評価値がない棋譜を除外
  • 全ての指し手について評価値が±170以内

ここまでは以前と同じで、次の条件が中盤を抽出する条件になる。

  • 32手目以降80手目までで、評価値の絶対値が150を超えた直前の局面

作成したスクリプト
DeepLearningShogi/csa_to_gokakusfen.py at defc83590f62338956ec941ffd60ca34e2f9e26c · TadaoYamaoka/DeepLearningShogi · GitHub

作成コマンド:

python -m dlshogi.utils.csa_to_gokakusfen floodgate\2019-2022 floodgate32-80.sfen --moves1 32 --moves2 80 --less_than_moves2 --eval2 150

成果物

全部で8187局面が抽出できた。

中盤互角局面集 · GitHub

戦型分類

戦型別の件数は以下の通りである(上位20件を表示)。

CSVにしたものはこちら。
中盤互角局面集(戦型分類) · GitHub

棋力測定

初手開始局面から測定した場合に、dlshogiと水匠が互角になる条件(水匠のノード数を5000倍)で、作成した中盤互角局面集で測定した。

   # PLAYER               :  RATING  ERROR  POINTS  PLAYED   (%)  CFS(%)    W    D    L  D(%)
   1 suisho5-16thx5000    :    23.5   45.8    33.0      60    55      84   30    6   24    10
   2 pre33                :   -23.5   45.8    27.0      60    45     ---   24    6   30    10

White advantage = 113.54 +/- 48.57
Draw rate (equal opponents) = 10.65 % +/- 4.17

pre33が、dlshogi 30bの5万プレイアウト。
suisho5-16thx5000が、水匠5のノード数をdlshogiの5000倍にしたもの。

※cshogi.cliで連続対局する場合は、--opening-movesを80以上にする。

中盤互角局面集を使った場合は、序盤からでは互角だった条件でも、水匠の方が勝率が高いことがわかった。
このことから、dlshogiは、序盤から優勢を築いて勝つことが多いことがわかる。

現在中終盤の精度改善に取り組んでいるので、この互角局面集で精度が改善されたか測定を行うつもりである。

将棋AI実験ノート:dlshogiと水匠で評価値の割れる局面の精度改善

第3回世界将棋AI電竜戦では、先手の角換わり定跡で、dlshogiが後手番で後手優勢と評価している局面から、定跡を抜けてから反省して負けることがあった。
dlshogiと水匠で評価が分かれる場合、dlshogiが正しくてそのまま勝ち切ることも多いが、特に中盤以降で読みが重要な局面で水匠に読み負けることがある。

電竜戦での例

8回戦の水匠とdlshogi with HEROZ 20bの対局では、85手目の先手の8三角をdlshogiは読めていなかった。

電竜戦 - 棋譜中継

この手は、水匠5でも1億ノードくらい読む必要がある。

エクスプロイタの学習

dlshogiの強化学習では、比較的少ない探索(1万ノード)で自己対局しているため、深く読むと評価が変わる手は指されない。
多少のランダムノイズも加えているが、選ばれる確率は低い。

対策として、評価値が低い手でも一定の確率で選ぶようにして棋譜を生成し、メインのモデルの弱点を見つけるモデルを学習する。
この方法で、メインのモデルに対して勝率の高いモデルを作成できることが確認できている。

ただし、それでも上記のような深い読みが必要な局面が改善されるには時間がかかる。

より直接的に修正する方法(提案手法)

より直接的に評価を誤る局面を修正するために、dlshogiと水匠で長めの思考時間で連続対局して、評価が割れる局面を抽出し、その局面を開始局面として棋譜を生成するようにする。

評価値を修正するには、正しい手を指された後の局面で、候補手のどれを指しても劣勢であることを学習する必要がある。
そのため、実際に指した手以外の手についても調べる必要がある。
ただし、すべての候補手を調べると局面数が増え過ぎるため、dlshogiの方策の確率が、実際に指した手以上の手について調べるようにする。
このように開始局面集を作成し、その開始局面集で連続対局を行った棋譜を学習することで、評価値が修正されることが期待できる。

上記の誤った局面について、この方法を試したことろ、比較的少ないノード数で正しい手を見つけられることが確認できた。

修正したいのは上記の局面だけではないので、過去に棋力測定のために水匠とdlshogiで連続対局対局した際の棋譜から、評価が割れる局面を抽出して開始局面集を自動作成した。

より一般化できないか

上記の方法は、水匠とdlshogiの連続対局から抽出しているが、水匠が固定だと限界があるため、できれば他のソフトを使わずに学習したい。
水匠の代わりに探索ノード数を増やしたdlshogiを使い、深く読んだ場合に評価が変わる局面を抽出することで同様の学習ができる可能性がある。

まとめ

現状のdlshogiは、中終盤の読みが重要な局面で評価を誤る場合がある。
自己対局のみでこれを改善するのは難しいため、より直接的に評価を修正する方法を考えた。
実際、評価を誤る局面一つを対象に、試したところ効果があることが確認できた。
この方法で、中終盤の精度を徐々に改善していきたい。

拡散モデルの実装を理解できるノートブック

拡散モデルの実装を理解するために、こちらのノートブックがとても分かりやすかったので紹介する。
diffusion-models-class/unit1 at main · huggingface/diffusion-models-class · GitHub

拡散モデル(DDPM)を、以下のように段階的に実装して確認できるようになっている。

  1. 画像に一様ランダムのノイズを加える
  2. UNetでノイズを加えた画像から元画像を予測する
  3. ランダム画像から段階的にUNetでノイズを除くことで鮮明な画像を生成する
  4. UNetをDiffusersのUNetに置き換えることでより鮮明な画像が生成できることを確認する
  5. ノイズを一様ランダムではなくガウス分布に変更し、あるタイムステップでのノイズを算出する
  6. 元画像ではなくノイズを予測するようにする
元のノートブックにGoogle翻訳を追加したノートブック

説明を読みながらセルを順番に実行していくことで、実装の概要が理解できた。
論文へのリンクもあって、より深く調べる際にも参考になる。

floodgateの戦型別先手勝率の変化

先日の第3回世界将棋AI電竜戦では、水匠の先手角換わり定跡の勝率の高さが注目された。
そこで、最近の将棋AI同士の対局で、戦型別の勝率に変化があるか調査した。

以下の調査では、戦型の分類にMizarさんが公開されているjsonの定義ファイルを使用している。

第3回世界将棋AI電竜戦

第3回世界将棋AI電竜戦のA級の全対局の出現回数が2以上の戦型別の勝率は以下の通りである。

戦型 回数 出現率 先手勝率 後手勝率 引分率
角換わり 25 30.5% 56.0% 36.0% 8.0%
相掛かり 14 17.1% 71.4% 28.6% 0.0%
角換わり,先手向かい飛車 4 4.9% 0.0% 100.0% 0.0%
先手横歩,角換わり 3 3.7% 100.0% 0.0% 0.0%
後手四間飛車,先手船囲い 3 3.7% 100.0% 0.0% 0.0%
後手三間飛車 3 3.7% 66.7% 33.3% 0.0%
角換わり,先手腰掛け銀 3 3.7% 66.7% 33.3% 0.0%
後手三間飛車,後手片美濃囲い 2 2.4% 50.0% 50.0% 0.0%
先手四間飛車,角換わり 2 2.4% 50.0% 50.0% 0.0%
先手四間飛車,後手船囲い,先手片美濃囲い,角換わり 2 2.4% 0.0% 100.0% 0.0%
後手中飛車 2 2.4% 50.0% 50.0% 0.0%

先手勝率は、相掛かりが71.4%と高い。これは、dlshogiが主に相掛かりを採用したためと思われる。
角換わりは56.0%で、相掛かりと比べると高くない。これは、水匠以外のソフトも角換わりを採用しているためと思われる。
また、角換わりは引分率が高く、千日手になりやすい戦型と言える。

floogateの棋譜

floogateの棋譜を年別に調査した。
R3800以上のソフト同士の対局でフィルターし、上位10個の戦型を記載する。

2019年
戦型 回数 出現率 先手勝率 後手勝率 引分率
角換わり 734 16.5% 52.5% 36.0% 11.6%
相掛かり 219 4.9% 47.9% 42.9% 9.1%
相掛かり,先手横歩 183 4.1% 75.4% 21.3% 3.3%
相掛かり,先手横歩,後手横歩 127 2.9% 79.5% 18.1% 2.4%
後手四間飛車,先手船囲い 106 2.4% 63.2% 32.1% 4.7%
後手四間飛車 84 1.9% 66.7% 29.8% 3.6%
相掛かり,先手横歩,後手横歩,角換わり 64 1.4% 87.5% 12.5% 0.0%
角換わり,後手向かい飛車 61 1.4% 49.2% 49.2% 1.6%
角換わり,後手早繰り銀 60 1.3% 43.3% 38.3% 18.3%
後手早繰り銀 58 1.3% 48.3% 39.7% 12.1%
2020年
戦型 回数 出現率 先手勝率 後手勝率 引分率
角換わり 1619 18.9% 49.3% 39.0% 11.7%
相掛かり 652 7.6% 45.4% 44.5% 10.1%
相掛かり,先手横歩 255 3.0% 67.1% 30.6% 2.4%
後手四間飛車,先手船囲い 253 3.0% 51.0% 45.5% 3.6%
相掛かり,先手横歩,後手横歩 238 2.8% 76.5% 21.0% 2.5%
後手四間飛車 212 2.5% 54.7% 41.0% 4.2%
先手四間飛車,後手船囲い 192 2.2% 59.9% 36.5% 3.6%
角換わり,後手早繰り銀 151 1.8% 57.6% 33.8% 8.6%
後手カニ囲い 143 1.7% 40.6% 53.1% 6.3%
先手四間飛車 142 1.7% 52.8% 42.3% 4.9%
2021年
戦型 回数 出現率 先手勝率 後手勝率 引分率
角換わり 3472 26.8% 53.4% 37.2% 9.4%
相掛かり 1577 12.2% 49.5% 44.3% 6.2%
角換わり,後手早繰り銀 725 5.6% 67.3% 25.9% 6.8%
角換わり,先手早繰り銀,後手早繰り銀 403 3.1% 48.9% 47.9% 3.2%
先手早繰り銀 266 2.0% 43.2% 50.4% 6.4%
角換わり,先手早繰り銀 264 2.0% 48.9% 43.6% 7.6%
先手横歩 255 2.0% 43.1% 49.4% 7.5%
先手腰掛け銀,後手二枚銀雁木 251 1.9% 33.1% 55.0% 12.0%
先手腰掛け銀 235 1.8% 43.4% 44.7% 11.9%
相掛かり,先手横歩 187 1.4% 70.6% 26.7% 2.7%
2022年
戦型 回数 出現率 先手勝率 後手勝率 引分率
角換わり 1550 29.2% 55.9% 33.9% 10.2%
相掛かり 800 15.1% 56.8% 33.8% 9.5%
角換わり,後手早繰り銀 194 3.7% 61.3% 34.5% 4.1%
後手四間飛車 152 2.9% 77.6% 20.4% 2.0%
先手腰掛け銀 143 2.7% 23.8% 63.6% 12.6%
先手四間飛車 140 2.6% 42.1% 57.9% 0.0%
先手四間飛車,後手船囲い 140 2.6% 50.0% 47.1% 2.9%
先手横歩 113 2.1% 39.8% 50.4% 9.7%
後手四間飛車,先手船囲い 98 1.8% 65.3% 31.6% 3.1%
角換わり,先手早繰り銀 97 1.8% 54.6% 37.1% 8.2%
年度別の出現率と先手勝率の変化

角換わりと相掛かりの年度別の出現率と先手勝率をグラフにした。
青線が出現率で、オレンジ線が先手勝率である。


考察

floogateでは、2019年から2022年を通して、角換わりの出現率が最も高い。
角換わり、相掛かりともに年ごとに出現率が高くなっている。

先手勝率は、2020年に一時的に低くなっている(引分率が高いため)が、それ以降は角換わり、相掛かりともに先手勝率が上昇している。
角換わりのみが特に先手勝率が高くなっている傾向はない。

まとめ

角換わりの先手勝率が、相掛かりに比べて高くなっている傾向があるかと思い、戦型別の勝率を調べたが、特にその傾向はみられなかった。
ただし、floodgateでは、角換わり、相掛かりともに、先手勝率は上昇している。

どの駒が評価値に寄与しているかを可視化する

dlshogiのモデルに盤面を入力すると、その盤面の評価値(勝率)を出力できる。
その際、どの駒が評価値に寄与しているか可視化できると、AIがどこに注目しているのかがわかる。
以前に、Attention Branch Networkを使って可視化を試したが、今回は、駒を除くという単純な方法で、可視化を試してみた。

提案手法

dlshogiは、盤面(駒の配置と持ち駒)をモデルに入力して、指し手の確率(方策)と評価値(勝率)を出力している。

現在の盤面を入力して推論した結果と、盤面の盤上の駒を一つ除いて推論した結果の差を見ることで、除いた駒の相対的な価値がわかる。
持ち駒の場合は、一つだけ除くと、複数枚ある場合に価値が変わらない場合があるため、同じ種類の持っている駒をすべて除くようにする。

これをすべての駒に対して行い、それぞれの盤面を推論することで、各駒の相対的な価値を求めることができる。

実装

dlshogiは、駒の利きや王手についても特徴量に加えているため、特徴量を加工するのではなく、駒を除いた盤面から特徴量を作すように実装した。
駒を除く処理は、sfenの文字列を加工して行った。
推論は、駒を除いた各盤面をミニバッチにすることで、1回の推論で計算できる。

gist.github.com

可視化

とりあえず確認用に、Excelのカラースケールで数値の大きさを色で表して、盤面画像に重ねて表示するようにした。

結果

第3回電竜戦A級8回戦の水匠 vs dlshogi with HEROZ 20bの棋譜から抽出した局面からを可視化した結果は以下の通り。

84手目で、水匠は定跡、dlshogi with HEROZ 20bは後手が少し良し評価している局面である。
先手の駒の赤色が、先手の評価に寄与している駒を示していて、
後手の駒の青色が、後手の評価に寄与している駒を示している。


98手目の先手が優勢になっている局面では、以下のようになる。

同じ位置にある4八金の価値が小さくなっているなど、比較すると違いが見られる。
なんとなく駒の働きが数値化できていそうである。

まとめ

dlshogiのモデルを使って、どの駒が評価値に寄与しているか可視化を行った。

以前に、Attention Branch Networkを使ってAIが注目している箇所の可視化を行ったが、今回の方法は各駒の相対的な価値を求めているため、より解釈がしやすい。
また、モデルの構成を変更する必要がないため、既存モデルを使って可視化を行うことができる。
今回は、1つの駒だけを除いたが、同様の方法で2つ以上の駒の組み合わせを考慮することもできる。