TadaoYamaokaの開発日記

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

Jupyter QtConsoleのTips

ほぼ自分用のメモ。

OSのコマンド実行

先頭に「!」を付ける。
例)

!dir

参考:IPython reference — IPython 8.1.0 documentation

グラフをインラインで表示
%matplotlib inline

参考:IPython reference — IPython 8.1.0 documentation

グラフを別ウィンドウで表示
%matplotlib

グラフをpngや、svgなどフォーマットを選んで保存できる。

随時追記予定

将棋AIの進捗 その9(千日手対応)

dlshogiを千日手に対応させました。

対応方法は以下の通り。

  • value networkで評価中に千日手チェックを行い、value networkの評価が終わったら、value networkの値を使わずに千日手チェックの結果を使うようにする。
  • 同じ局面でも経路によって千日手チェックの結果は異なるため、ハッシュのvalue networkの評価値を上書きしない。
  • 同じ局面を探索したときに、以前に千日手になった局面は、再度千日手チェックを行い、千日手の場合、探索を打ち切る。

経路が異なると千日手チェックの結果が変わることに注意が必要です。
千日手チェックは、AperyのPosition::isDrawが使えたので楽に実装できました。
千日手チェックを自分で実装すると大変なので、ライブラリはありがたいです。

効果

対応前は、GPSfishと50回対局で8回千日手になりましたが、対応後は1回も千日手にはならないようになりました。
ループする無駄な局面を探索しなくなるので、強さも上がるかと思いましたが、勝率が上がることはなかったです。

将棋でディープラーニングする その49(再学習)

ResNetのブロック数を10にして、elmoで生成した深さ8の局面を使って、学習をやり直しています。
クラッチからの学習も試したいところですが、モデルの性能を評価するには、既存将棋ソフトで生成した棋譜は役に立ちます。

tanhバージョン

はじめ、vlaue networkの出力をtanhにしたモデルで学習していましたが、3.4億局面学習してもGPSfishに1勝もできないので以前より弱くなりました。
policyの一致率は45.2%、valueの一致率は77.8%と一致率の数値は、以前のモデルの3.4億局面学習時がpolicyが42.9%、valueが77.6%であったのに比べて高い数値になっています。
一致率は高いのに弱くなった理由について調べたところ、polciyの予測する指し手が以前に比べて絞られすぎており、数手の予測手以外の手をMCTSで探索しないようになっていました。
学習データにフィットしすぎていて、policyが尖った状態になっていました。
policyの損失関数は同じなのに、valueの出力がsigmoidからtanhに変わって損失が交差エントロピーからMSEに変わったことで、policyにも影響が出たようです。
policyとvalueの損失の割合を変えるなどで解決できるかもしれませんが、tanhを使うのはやめることにしました。

sigmoidバージョン

続いて、以前と同様にvalue networkの出力にsigmoidを使って、ResNetのブロック数を5から10にしたモデルで学習をやり直しました。
4億局面学習した時点で、GPSfishに1手3秒で、50回対局で38%勝つようになりました。

Eloレーティングでは、GPSfishのレーティングを2800とすると、
2800-400 \log_{10}(\frac{100}{38}-1) = 2714
となり、以前のdlshogiと同等の強さになっています。
以前のdlshogiは、35.8億局面を3エポック学習していたのに対して学習効率が大幅に向上しています。

ResNetのブロック数を増やしたことで、過学習するのではないかという懸念がありましたが、そのようなことはないようです。
[1710.03667] High-dimensional dynamics of generalization error in neural networksによると、DNNの場合、大規模にしても学習データが十分にあると汎化性能を失わないそうです。

以前のdlshogiのモデルはバグがあったので、ResNetのブロック数だけの効果が測れていないので別途検証をする予定です。

世界コンピュータ将棋選手権 ライブラリ登録

dlshogiをライブラリ登録しました。
コンピュータ将棋選手権使用可能ライブラリ

ディープラーニングを使って将棋AIを開発したい方のお役に立てば幸いです。

第5回電王トーナメントバージョンは、いろいろとバグがあったので、↓このコミットがバグを修正したソースになります。
github.com
ただし、モデルファイルの互換性はなくなっています。
公開した学習済みモデルを実行するには、第5回電王トーナメントバージョンが必要です。

将棋でディープラーニングする その48(ResNet)

これまでニューラルネットワークの構成に、5ブロックのResNetを使ってきたが、層を増やすると精度がどれくらい上がるか実験を行ってみた。

これまでは、ResNetの構成は、こちらの論文([1603.05027] Identity Mappings in Deep Residual Networks)で精度が高いとされている「full pre-activation」の構成に、こちらの論文([1605.07146] Wide Residual Networks)で提案されている畳み込み層の間にdropoutを加えた構成を使用していた。

一方、AlphaGo Zeroでは通常のResNetの構成を使用している。

そこで、通常のResNet構成で層を増やした場合とWideResNetで層を増やした場合でも比較を行った。
また、フィルター数も変更して比較した。

比較したパターンは以下の通り。

ResNet構成 ブロック数 フィルター枚数
パターン1 WideResNet 5 192
パターン2 通常 5 192
パターン3 通常 10 192
パターン4 通常 10 128
パターン5 通常 10 64
パターン6 WideResNet 10 192

測定結果

測定条件
  • 訓練データ:1億局面
  • テストデータ:100万局面
  • 学習率:0.01
  • 最適化:MomentumSGD
  • ミニバッチサイズ:64
  • 訓練局面elmoの自己対局で生成
  • policyとvalueマルチタスク学習
  • 1000万局面ごとに評価
policyのtest accuracy

f:id:TadaoYamaoka:20171121211820p:plain

valueのtest accuracy

f:id:TadaoYamaoka:20171121211840p:plain

学習時間

f:id:TadaoYamaoka:20171121210536p:plain
※1000万局面あたり
※パターン1とパターン6は1080Ti、残りは1080で学習したのでそのまま比較はできないが参考として記載

考察

policyのtest accuracy

10ブロック、192フィルターのResNet、WideRestがtest accuracyが高い値になっている。
層数を増やすと精度が上がることが確かめられた。

同じ10ブロックでも、フィルター枚数を64にすると、5ブロック192フィルターより精度が落ちている。
10ブロック、128フィルターで、5ブロック192フィルターと同じくらいになっている。
層数とフィルター枚数はともに重要であり、バランスをとる必要がありそうである。

valueのtest accuracy

傾向は、policyとほぼ同じとなった。

学習時間

ResNetのブロックを倍にすると学習時間は、1.76倍になった。
層を増やすと実行時のNPSにも影響するので、精度と学習時間、対局時の速度でバランスをとる必要がある。
どれがベストか探るには実験時間がかかりすぎる。
前回35億局面学習したときよりは精度を上げたいので、今後はとりあえず10ブロックで実験していこうと思う。

将棋でディープラーニングする その47(全結合)

AlphaGo Zeroでは、policy networkの出力ラベルを石の色×座標+passで表しており、全結合層で出力を行っている。
Fan Hui版AlphaGoでは1×1フィルターの畳み込み層を出力層としていた。
出力層を全結合にした理由は、論文では説明されていないが、精度が上がるため、もしくは単にpassを出力するためと思われる。

将棋AIでは、passがないため、1×1フィルターの畳み込み層で全候補手を出力できる。
全結合にすると計算量が増えるため、精度があがる効果がなければ、全結合にする必要はない。

そこで、出力層を1×1フィルターの畳み込み層とした場合と全結合層にした場合で精度の比較を行った。

1×1フィルターの畳み込み層の枚数は、前回の日記で説明した通り、駒の種類×移動方向+持ち駒の種類だけの枚数(101)とする。
全結合層のノード数は、駒の種類によって移動できない座標を除外したノード数(5839)とする。

以下のパターンで比較を行う。

パターン 出力層
1 1×1フィルターの畳み込み層
2 全結合層
3 1×1フィルターの畳み込み層の後に全結合層

比較結果

測定条件
  • 5ブロックのWide ResNet、3×3フィルター、192枚
  • 訓練データ:4000万局面
  • テストデータ:100万局面
  • 学習率:0.01
  • 最適化:MomentumSGD
  • ミニバッチサイズ:64
  • 訓練局面elmoの自己対局で生成
  • value networkとマルチタスク学習

policy networkの学習結果

train loss test accuracy 学習時間/1000万局面
1×1フィルターの畳み込み層 1.0002 0.4065 1:08:57
全結合層 1.0318 0.3957 2:17:10
1×1フィルターの畳み込み層の後に全結合層 1.0545 0.3926 1:39:37

考察

精度

全結合層のノード数は、移動できない座標を除外しているので、1×1フィルターの畳み込み層のラベル数(8181)よりもラベル数(5839)は少なくなくなっている。
そのため、精度が向上する効果があると予測したが、逆に精度が悪くなるという結果になった。
出力ラベルを減らす効果よりも、全結合にすることの影響が大きかったようだ。

全結合よりも、1×1フィルターの畳み込み層の方が精度が高くなる理由については、全結合は位置の情報が失われるためという説明をどこかで読んだような記憶がありますが、どなたかご存知でしたら教えてください。

このページとかには、パフォーマンスが改善するという記述がありますが、精度が上がる理由を説明している資料を探し中。

学習時間

全結合よりも、1×1フィルターの畳み込み層の方が計算量が少なくなり学習時間が短くなる。
測定結果でも、1×1フィルターの畳み込み層の学習時間が最も短かった。
全結合のみ(パターン2)の場合は、全結合への入力が192枚の画像となっており入力ノード数が多いため、学習時間が1×1フィルターの畳み込み層の約2倍になった。


前回の結果と合わせると、

  • 出力層は、1×1フィルターの畳み込み層
  • 出力ラベルは、移動先と移動方向で表現(移動する駒の種類は不要)

が、将棋AIのpolicy networkの出力層に最適と言えそうです。

なお、今回の実験の際に、今まで使っていたネットワークの出力層の直前の活性化層が漏れてたことに気づいたので修正しました。これも精度を落とす要因になっていました。

2017/11/21 追記

全結合よりも1×1フィルターの畳み込み層の方が精度が上がる理由を、はっきり説明できる資料は見つかりませんでしたが、以下のredditのスレッドで議論されている内容から、1×1フィルターの畳み込み層は空間の次元を保持して、色の次元を削減するために使用するようです。
www.reddit.com
全結合に比べて次元を削減できることで学習効率が上がるのか、空間の次元を保持することで将棋という位置が重要となるゲームで有効に働くかのどちらかではないかと思います。

将棋でディープラーニングする その46(出力ラベルの表現方法)

開発してるdlshogiでは、出力ラベルを(駒の種類×移動方向+持ち駒の種類)×座標で表現し、出力層にAlphaGoを参考に1×1の畳み込み層を使用している。
AlphaGo Zeroでは、出力ラベルを石の色×座標+passで表しており、全結合層で出力を行っている。
1×1の畳み込み層から全結合層に変えた理由は、論文では特に説明されていない。
精度を上げるため、もしくは単にpassを表現したかったためと思われる。

dlshogiでは、出力層に1×1の畳み込み層を使っているため、駒の種類によっては、移動できない座標にもラベルを割り当てている。
出力を全結合層にすると、移動できない座標にラベルを割り当てる必要はなくなり、割り当てるラベルを減らすことができる。
全結合層に変更することで精度があがるか検証してみたい。

今回は、全結合層の検証の前に、出力ラベルの表現方法について、以前から気になる点があったので検証を行った。

出力ラベルの表現方法の検証

将棋では、駒の移動があるため、座標だけでは、移動元が一意に決められない。
移動元も座標で表すと、移動先との組み合わせが多くなる。
そこで、dlshogiでは、以前に書いた通り、移動元は方向だけで表現している。
また、移動する駒の種類にもラベルを割り当てている。
移動方向は、駒の種類ごとに移動できる方向だけにラベルを割り当て、駒の成りも移動方向の一種として表現する。
出力ラベルは(駒の種類×移動方向+持ち駒の種類)×座標で表現される。
出力ラベルの合計は8181になる。(詳細は以前の日記を参照)

比較対象

元々、移動元を方向で表すアイディアは、not522/CNNShogiからヒントを得たものであった。
not522/CNNShogiでは、移動する駒の種類にはラベルを割り当てていないため、出力ラベルは、(移動方向(桂馬の動き含む)×成りの有無+持ち駒の種類)×座標となり、合計で(10×2+7)×9×9 = 2187となる。

dlshogiで駒の種類にもラベルを割り当てた理由は、異なる駒の移動を同じラベルとして学習すると、モデルに与える情報量が減るため、精度も落ちると考えたためである。

どちらの表現がよいか以前から気になっていたので比較実験してみた。

比較結果

測定条件
  • 5ブロックのWide ResNet
  • 訓練データ:3000万局面
  • テストデータ:100万局面
  • 学習率:0.01
  • 最適化:MomentumSGD
  • ミニバッチサイズ:64
  • 訓練局面elmoの自己対局で生成
  • value networkとマルチタスク学習

policy networkの学習結果

train loss test accuracy
駒の種類あり 1.0487 0.3824
移動方向のみ 1.0470 0.3889

考察

予測に反して、精度はほぼ同じとなった。
対局時に使用したときのレーティングに影響があるかも調べたいが、モデル学習に時間がかかりすぎるので検証はここまでにする。

出力層を全結合層にした場合でも、駒の種類ありと移動方向のみを比較してみたい。

2017/11/18 追記

訓練データを1億局面にして比較してみた。

train loss test accuracy
駒の種類あり 0.9990 0.4081
移動方向のみ 0.9957 0.4087

上記と同様に精度はほとんど変わらなようだ。

2017/11/19 追記

出力層の前の活性化関数が漏れているバグがあったため、修正して再測定した。

train loss test accuracy
駒の種類あり 0.9676 0.4150
移動方向のみ 0.9637 0.4174

※訓練データ:7000万局面
移動方向のみの方が良いという結果になった。