TadaoYamaokaの開発日記

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

dlshogiはどれくらい人間の指し手に近いか

コンピュータチェスでは、ディープラーニング系のAIは、従来型に比べて人間の指し手に近いという研究がある。
従来、人間の相手になるように、レーティングを下げるために、探索のノード数や深さを下げるということが行われていた。
しかし、人間にとっては不自然な指し手になるという課題があった。
ディープラーニング系のチェスAIを使うと、より自然に弱くできるという研究である。
The human side of AI for chess - Microsoft Research

コンピュータ将棋においても同じことが言えるのかdlshogiと水匠5を使って検証してみた。

検証には、将棋ウォーズの棋譜をお借りした。

dlshogiと水匠の条件

人間と同じくらいの強さになるように、dlshogiは、固定プレイアウト16,64,256,1024の4パターンで、バッチサイズ1とした。

floodgateでのレーティングは、プレイアウト64で3069になる。
低レーティング帯での探索ノード数と強さの関係 - TadaoYamaokaの開発日記

水匠5は、dlshogiとほぼ同じ強さになるように、固定ノード数1024,6400,25600,409600の4パターンとした。

一致率

人間の棋譜3万について、指し手の一致率を比較した結果は以下の通り。

棋譜のレーティング帯別に集計している。

考察
  • 水匠5に比べてdlshogiは、人間の指し手に近い(一致率が高い)
  • dlshogiはノード数を減らすほど、一致率が上がる
  • 水匠5は逆に、ノード数を減らすと一致率が下がる

従来型はノード数を減らすと不自然になるということが一致率から確かめられた。
また、コンピュータチェスと同様に、弱くした場合に、ディープラーニング系の将棋AIの指し手はより人間に近いことがわかった。

人間の棋譜を学習

人間の棋譜を学習した後に、一致率が上がるか検証した。

将棋ウォーズの棋譜を用いて、dlshogiのpolicyを追加学習(valueはdlshogiの推論結果を学習)した際の一致率は、以下の通り。

考察
  • 探索ノード数が少ないの場合に、より人間と一致率が高くなる
  • R1500付近が最も一致率が高い(棋譜の分布によると考えられる)
  • 探索ノードを増やすと、一致率が下がる

人間の棋譜を学習すると、一致率は、54%程度まで上がることがわかった。
棋譜はR1500付近が最も多いため、R1500付近との一致率が一番高くなった。
棋譜が十分にある場合、レーディング別に分けて学習すると、そのレーティング帯の指し手の傾向を学習できると思われる。

探索ノードは少ないほど、一致率が高い理由は、切れ負けでの対局のため人間はそれほど深くは読めていないため、浅い探索の方が一致率が高くなったと考える。

まとめ

コンピュータチェスの先行研究と同様に、コンピュータ将棋においても、ディープラーニング系の将棋AIは、従来型よりも、弱くした場合により自然な指し手になることが確かめられた。
また、人間の棋譜を学習することで、より人間らしい指し手を学習することができた。


この人間の棋譜を学習したdlshogiが、将棋ウォーズのCPUとして追加されています。
対局の際には、ぜひ遊んでみてください。

将棋ウォーズにログインすると、棋譜が見られます。振り飛車も指しています。
shogiwars.heroz.jp

将棋AI実験ノート:20ブロックの学習

ResNet15ブロックのモデルで生成した教師データを用いて、20ブロックのモデルを学習し、精度と強さを比較してみた。

モデルサイズ

15ブロックのモデルは、15ブロック224フィルタ
20ブロックのモデルは、20ブロック256フィルタ
1ブロックは畳み込み2層
活性化関数はSwish

教師データ

15ブロックのモデルの学習に使用した約32億局面を学習した。
floodgateの棋譜や従来型の将棋AIで生成した棋譜も一部含んでいる。

学習条件

バッチサイズ:4096
学習率:0.04から1エポックごとに1/2
重複局面の平均化あり
評価値の補正あり
12エポック学習

学習時間比較

1バッチ学習を1ステップとして、1000ステップ学習にかかった平均時間は以下の通り。

時間(時:分:秒)
15ブロック 0:05:41
20ブロック 0:07:35 133%

20ブロックのモデルは、学習に約1.33倍時間がかかっている。

精度比較

2017年~2018年6月のfloodgateのR3500以上の棋譜からサンプリングした856,923局面(重複なし)を使用して精度を比較した。
教師データにはfloodgateの棋譜も含んでいるが、テストデータの期間の棋譜は含んでいない。

なお、学習にテストデータを含めてしまうと精度が大幅に良く出てしまうので注意が必要である。
第2回電竜戦のGCTでは、方策の精度が0.60、価値が0.79になったと聞いていたが、dlshogiのテストデータを使うとそれぞれ0.49、0.74くらいで、GCTのテストデータを学習に含めていたことで精度が良く見えていた(リークした)状態であった。

15ブロックのモデルは、教師データ継ぎ足しながら学習しているため、完全に同じではないが、精度を比較した。
SWAを適用した後のモデルで比較する。

エポック数 方策精度 価値精度
15ブロック 14エポック 0.5269174 0.7633635
20ブロック 12エポック 0.5374750 0.7670151

20ブロックのエポック数は15ブロックにまだ追いついていないが、精度は、15ブロックよりすでに大幅に良くなっている。

強さの比較

ブロック数が増えると、探索速度が落ちるため、強さの比較は、同一探索ノード数の条件、同一持ち時間での条件で比較した。

同一探索ノード数

探索ノード数を10万に固定して比較した結果は、以下の通り。
固定4000万ノードの水匠5も加えたリーグで測定した。

   # PLAYER             :  RATING  ERROR  POINTS  PLAYED   (%)  CFS(%)    W    D     L  D(%)
   1 pre21-nodes100k    :    68.4   12.1  1010.0    1600    63     100  958  104   538     6
   2 pre17-nodes100k    :    14.2   11.7   843.5    1600    53     100  790  107   703     7
   3 suisho5-40m        :   -82.6   11.7   546.5    1600    34     ---  511   71  1018     4

White advantage = 95.31 +/- 7.34
Draw rate (equal opponents) = 6.38 % +/- 0.53

※pre21が20ブロック、pre17が15ブロック

20ブロックのモデルが、R+54.2になっている。
固定ノード数では、推論速度によらずモデルの精度のみで比較するため、テストデータでの精度比較の通り、20ブロックの方が強いという結果になった。

自己対局は、ノード数固定で行っているため、今後は20ブロックのモデルを使って自己対局を行うことにしたい。

同一持ち時間

持ち時間400秒、1手2秒加算で対局させて強さを比較した。
1GPU3スレッドのdlshogiとほぼ同じ強さになるように、32スレッド水匠5の持ち時間は1600秒として、リーグ戦で測定した。

   # PLAYER            :  RATING  ERROR  POINTS  PLAYED   (%)  CFS(%)    W    D    L  D(%)
   1 suisho5-32thx4    :     7.5   19.3   254.5     495    51      62  215   79  201    16
   2 pre17             :     2.4   19.8   253.0     501    50      76  217   72  212    14
   3 pre21             :    -9.9   19.7   238.5     496    48     ---  201   75  220    15

White advantage = 109.25 +/- 11.94
Draw rate (equal opponents) = 16.05 % +/- 1.46

※pre21が20ブロック、pre17が15ブロック

15ブロックの方が、R+12.3という結果になった。
ただし、CFS(信頼度)は76%であり、誤差の範囲である。

20ブロックは精度は高くなったが、同一持ち時間では、強さは15ブロックと同程度である。

NPSの比較

15ブロックと20ブロックで、探索速度(NPS)を比較した。
floodgateの棋譜からサンプリングした100局面で、8GPU4スレッドで1秒探索した際の結果は以下の通り。

               pre17          pre21
count     100.000000     100.000000
mean   380754.050000  303340.570000
std     38671.979844   22344.165674
min    250165.000000  223958.000000
25%    366500.750000  291622.500000
50%    391344.000000  306276.500000
75%    409446.500000  318108.250000
max    431834.000000  373004.000000

※pre21が20ブロック、pre17が15ブロック

20ブロックの方のNPSは平均で79.6%に低下している。

まとめ

15ブロックと20ブロックで同じ教師データを学習した場合のモデル精度と強さを比較した。
モデル精度は、20ブロックが大幅に高くなることがわかった。
強さは、同一ノード数の場合、20ブロックがR+54.2になり、同一持ち時間ではほぼ同じになった。

15ブロックのモデルは、追加学習しても強くならなくなっているため、今後は20ブロックのモデルで学習を行うつもりである。
現状では、モデル精度と探索速度が釣り合っている状態のため、大会の持ち時間で比較した上で、大会でどちらのモデルを使うか決めたい。

定跡作成は固定ノード数で行えるため、20ブロックのモデルで行った方がよさそうである。

Unityで将棋アプリの開発 その13(棋譜解析)

作成している将棋アプリに、対局後の棋譜解析機能を実装した。

機能内容

対局終了後に表示されるダイアログで、「棋譜解析」ボタンを押すと棋譜を解析して形勢グラフを表示する。
f:id:TadaoYamaoka:20220326121851p:plain

f:id:TadaoYamaoka:20220326122029p:plain

対局中のプレイヤー手番では、プレイヤー側の評価を非同期で行っているので、評価結果を残しておき、まずはその結果をすぐに表示する。
AI側の評価は、AIのレベルが低い場合、温度パラメータ等を変更しているため、AIの探索結果をそのまま使えないので、再評価する。
再評価は非同期で行い、解析が終わったものからグラフに反映される。

解析時間を考慮して、再評価時の探索は64プレイアウトに制限する。

棋力測定モードではAI側の探索結果がそのまま使えるので、再評価なしですぐに表示できる。

好手、悪手(10%)、悪手(20%)はマークするようにした。

局面の移動

棋譜解析では、形勢グラフのタップもしくは、ボタンで、局面の移動ができる。
局面を移動すると、512プレイアウトまで解析を行い形勢グラフに反映する。

移動した局面で、ヒントと定跡を使用して、検討ができる。

f:id:TadaoYamaoka:20220326121750p:plain

実装上苦労した点

実装には、想定以上に時間がかかった。
グラフを表示するために、線を引く必要があるが、Unityで綺麗な線が引けず試行錯誤する必要があった。
解決した方法については、別途記事にした。
UnityのLineRendererのアンチエイリアシングを有効にする - TadaoYamaokaの開発日記
また、線が折れると線が細くなる現象が起きたが、Corner Vertecesを1にすることで解決できた。


あと、スマホの画面に、形勢グラフを見やすいように収めるのに、グラフの表示領域や文字サイズの調整を繰り返す必要があった。
Unityでこの調整を行うと、確認のためにアプリを実行するのにビルドで1分くらい待たされるのでかなり効率が悪い。
デザインは、はじめにAdobe XDとかで行う方がよいと思う。

まとめ

作成している将棋アプリに棋譜解析機能を実装した。
対局後にどの指し手が悪かったか振り返ることができるので、将棋の勉強に役立つと思う。

対局中に非同期で評価を行っていて、棋譜解析の結果は待つことなく表示されるので、ストレスなく使うことができる。
このアプリを使う理由になってくれればよいと思っている。

最低限、遊べる機能は実装できたが、既存のアプリにくらべて見劣りしているので、もう少しクオリティを上げてからリリースしたい。

次は、互角局面か、手合割を実装したい。

UnityのLineRendererのアンチエイリアシングを有効にする

LineRendererで斜めの線を引くと、以図のようにジャギーが発生する。
f:id:TadaoYamaoka:20220323204954p:plain

原因がわからずネットの情報をいろいろ試したが解決しなかった。

プロジェクトのアンチエイリアシングの設定

たまたま、新規に作成したシーンでLineRendererで線を引いて、プロジェクトのアンチエイリアシング(Anti Aliasing)の設定を「4x Multi Sampling」に変更したことろ、滑らかになった

f:id:TadaoYamaoka:20220323205619p:plain

デフォルトのシーンでは有効にならない

しかし、初期作成されるデフォルトのシーン(SampleSceine)では、アンチエイリアシングの設定を変更しても滑らかにならないため、差分を確認したことろ、カメラの設定の「MSAA」の設定が、デフォルトのシーンでは、「Off」になっていることがわかった。
設定を「Use Graphics Settings」に変更することで、デフォルトのシーンでもLineRendererのアンチエイリアシングが有効になった。

f:id:TadaoYamaoka:20220323205738p:plain

以下の通り、線が滑らかに表示される。

f:id:TadaoYamaoka:20220323210055p:plain

まとめ

LineRendererは、デフォルトのシーン(SampleSceine)ではアンチエイリアシングが有効にならない。
カメラの「MSAA」の設定を「Use Graphics Settings」にすることで、有効になる。

デフォルトのシーン(SampleSceine)では、MSAAの設定が「Off」になっているので、注意しよう。

Unityで将棋アプリの開発 その12(詰み探索)

作成している将棋アプリに詰み探索を実装した。

AIのレベルと詰み探索

スマホ向けにMCTSで少ないプレイアウトだと、どうしても詰みの見逃しが多くなる。
練習用の強さだと、長手数の詰み探索はいらないが、一番強いレベルでは詰みを見逃さないようにしたい。

強さは、接待dlshogiの方法を使用した、わざとに負けない限りは勝たない練習用と、プレイアウト数とランダムプレイの閾値を変えて強さを段階的(15級~七段)に変えたものを用意している。
詰み探索の深さも段階的に深く設定して、強さを調整することにした。

実装方法

ルート局面でDfPnによる長手数の詰み探索を実行するようにした。

ノード数を最悪でも500msくらいで完了すように制限して、探索開始時にメインスレッドで実行するようにしたが、500msでもUIの引っかかりを感じるため、非同期で処理するようにした。

コルーチンでメインスレッドで非同期に実行しようとすると再帰処理の実装がややこしくなるため、Task.Runで別スレッドでMCTSと並行で実行するようにした。
スマホでマルチスレッドにするとMCTSの方が大幅に遅くなるかと心配したが、Pixel5では遅くなった気はしないので大丈夫なようだ。
シングルコアのスマホだと厳しそうだが、今時どのスマホもマルチコアなので大丈夫だろう。

置換表サイズ

dlshogiのDfPnの実装では、あらかじめ置換表を固定サイズで確保しているが、スマホだとメモリの制約が厳しいため、置換表はC#のDictionaryで実装して、置換表のエントリもListで動的に確保するようにした。
メモリを使い過ぎないように、探索ノード数を固定して、メモリ使用量を抑えるようにする。

ヒントでの詰み探索

ヒント機能でも詰み探索を並列で行い、詰みが見つかった場合は詰みの手順を表示するようにした。
ノード数は1000、深さは17に制限している。
dlshogiと同様、詰みの手順は最短にならない課題があるため、対策は別途検討したい。

f:id:TadaoYamaoka:20220320174647p:plain

まとめ

将棋アプリに長手数の詰み探索を実装した。
スマホでは、プレイアウト数はあまり増やせないため、MCTSの仕組み上、詰みの見逃しが起こりやすくなる。
AIのレベルを上げた場合に、詰みの見逃しがあると残念な感じがするので、詰みの見逃しが起きないようにした。

次は、棋譜解析機能を実装したい。

Unityで将棋アプリの開発 その11(棋力測定)

作成している将棋アプリに棋力測定モードを実装した。

実装内容

先日の調査で、dlshogiの探索で測定した勝率の平均損失とレーティングに相関があることがわかったので、AI相手に対局した棋譜を蓄積して、そこからレーティングを推定する機能を実装した。

1棋譜のみでは誤差が大きいため、過去の棋譜の勝率の平均損失の指数移動平均を使用するようにした。
対局するほど推定が正確になり、直近の対局ほど重視されるようになる。

誤差範囲も表示したいが、別途検討することにする。

先日の調査では、1局面512プレイアウトとしたが、スマホでは20秒くらいかかるので、64プレイアウトとした。
線形近似した係数も再調整が必要になるが、一旦先日の調査した値を使用した。

結果は以下のように表示する(自分で2対局だけで試した結果)。
f:id:TadaoYamaoka:20220319143239p:plain

対局中にもリアルタイムで、指標を表示するようにする。
棋力測定モードでは、待ったとヒント、定跡は使用できないようにしている。
f:id:TadaoYamaoka:20220319141447p:plain

タイトル画面

普通の対局と棋譜測定を選べるように、タイトル画面を実装した。

f:id:TadaoYamaoka:20220319143751p:plain

今のところボタンを配置しただけで、まったくデザインは考慮していない。
初回リリース時の機能が固まった後に、デザインしたいと思っている。
デザインの経験がほぼないのでプロに頼みたいところだが、趣味のアプリなので自分でデザインも勉強しながら行おうと思っている(自分でしょぼくないと思えるレベルが目標)。

まとめ

将棋アプリに棋力測定モードを実装した。
AIとの対局の棋譜の蓄積を元にレーティングを推定するようにした。
誤差がどれくらいかも表示した方が親切なので、別途検討したい。

次は、終盤の棋力を上げるために、詰み探索を実装したい。
合わせて、長手数の詰みチェック機能と、詰将棋将棋も実装したい。

dlshogiを使って棋譜から棋力を推定する

たややんさんが実施していた棋譜から棋力を推定する方法をdlshogiを使って検証してみた。

使用する棋譜

将棋倶楽部24名人戦対局の2452棋譜を使用した。

対局者間のレーティングの分布は以下の通り。
f:id:TadaoYamaoka:20220316232621p:plain

対局者のレーティングのヒストグラムは以下の通り。
f:id:TadaoYamaoka:20220316232733p:plain

dlshogiの設定

棋譜の各局面について、バッチサイズ1で512プレイアウトで探索を行い評価値と最善手を取得する。

勝率の平均損失

まずは、各棋譜ごとに、勝率の平均損失を調べた。

勝率の平均損失は、(着手後の局面の勝率 - 着手前の局面の勝率)の全局面の平均を、各棋譜のプレイヤーごとに求める。

序盤はプレイヤーの好みによるため、分析開始手数は12とした。
詰みの局面の前後は勝率差が極端に大きくなるため、除外した。

棋譜のプレイヤーのレーティングと勝率の平均損失の関係は以下の通りとなった。
f:id:TadaoYamaoka:20220316234456p:plain

棋譜ごとだと、相関係数は-0.22であり、レーティングと勝率の平均損失の相関は低い。

1棋譜のみで、レーティングを推定するのは難しそうである。

プレイヤーごとに集計

次にプレイヤーごとに集計して、レーティングと勝率の平均損失の関係を調べた。
10棋譜以上あるプレイヤーを対象とした。

プレイヤーごとの棋譜数の統計値は以下の通り。

count    309.000000
mean      15.443366
std        4.381284
min        1.000000
25%       14.000000
50%       17.000000
75%       19.000000
max       22.000000

プレイヤーごとの、レーティングと勝率の平均損失の関係は以下の通りとなった。
f:id:TadaoYamaoka:20220316235218p:plain

相関係数は、-0.59となり、10棋譜以上あると、相関は高くなったが、それでもあまり高くない。

レーティング帯で集計

100区切りのレーティング帯ごとで集計して調査した。

レーティング帯ごとの棋譜数は、以下の通り。
f:id:TadaoYamaoka:20220316235825p:plain

レーティング帯ごとの、レーティングと勝率の平均損失の関係は以下の通りとなった。
f:id:TadaoYamaoka:20220316235453p:plain

相関係数は、-0.95となり、強い相関が見られた。

一致率

レーティング帯ごとの一致率についても確認した。
f:id:TadaoYamaoka:20220317000619p:plain

相関係数は、0.97となり、勝率の平均損失よりも強い相関が見られた。

dlshogiの最善手は、従来ソフトよりも人間の手との一致率が高いため、一致率もレーティングの指標にできそうである。

悪手率

1対局で勝率が10%下がる悪手を指した割合を悪手率として、レーティング帯ごとの悪手率についても確認した。

f:id:TadaoYamaoka:20220317000925p:plain

相関係数は、-0.94となり、悪手率にも強い相関が見られた。
勝率の平均損失よりは少し低い。


20%下がる場合を悪手とした場合は、以下の通り。
f:id:TadaoYamaoka:20220317001144p:plain

相関係数は、-0.94となり、20%とした場合もほぼ同じ傾向である。

開始手数

開始手数を12としたが、先行研究では、40手以降としている。

40手以降とした場合の、レーティングと勝率の平均損失の関係は以下の通り。

f:id:TadaoYamaoka:20220317001448p:plain

相関係数は、-0.89となり、12手以降よりも低くなった。

先行研究では従来型のソフトを使用しているため、序盤の評価が不正確であることが影響していた可能性がある。
dlshogiは、序盤から正確な評価ができるため、序盤も含めた方が相関は高くなる。

0手目からとすると、相関係数は下がる。
最序盤の手は、好みの戦型によることを裏付けていると考える。
f:id:TadaoYamaoka:20220317002643p:plain


同様に評価値の閾値についても調査したが、先行研究は評価値の絶対値が200以内の局面を使用していたが、閾値は設けない方が相関係数は高くなった。
評価値の閾値を1000にした場合の相関係数は、-0.91となった。
f:id:TadaoYamaoka:20220317001930p:plain

まとめ

dlshogiで評価した勝率の平均損失とレーティングには強い相関があることがわかった。
ただし、1棋譜のみから推定すると誤差が大きく、レーティングを推測するには少なくとも10棋譜以上は必要である。

dlshogiの最善手との一致率にもレーティングと強い相関があることがわかった。
また、悪手率についても、強い相関がある。

先行研究では評価に序盤の局面を含めると相関係数が低くなるが、dlshogiの場合は序盤の局面を含めても相関係数が下がらないことがわかった。
これは、従来ソフトよりも序盤を正確に評価できることによると考える。

dlshogiによる勝率の平均損失がレーティングの推定に有効であることがわかったので、調査結果を元に作成している将棋アプリの棋力推定機能を実装する予定である。