TadaoYamaokaの日記

山岡忠夫 Home で公開しているプログラムの開発ネタを中心に書いていきます。

将棋AIの進捗 その2

elmo_for_learnを使ってdepth8で35億局面の生成ができたので、DNNの学習を開始しました。

前に7.5億局面を学習したときは、4日と20.5時間かかったので、35億局面を学習するには22日15.6時間かかる見込みです。

elmo_for_learnで生成した局面には重複局面が4%程含まれるため、前処理として重複局面を削除する処理を行いました。

自作のC++ツールで、std::uniqueを使って重複を削除していますが、35億局面のファイルは合計で127GBあってメモリに乗らないため、ファイルを分割し、分割したファイル同士で重複を削除するツールを作成して処理しました。
ElmoTeacherDecoder/hcpe_uniq2 at master · TadaoYamaoka/ElmoTeacherDecoder · GitHub

DNNの学習では、学習データがシャッフルされていることが精度を上げるために重要なため、これもC++でツールを作成し、std::shuffleでシャッフルを行いました。
これもメモリに乗らないため、まずは全データのインデックス(連番)を格納した配列を用意し、それをシャッフルしたあと、インデックスを使って実際のデータを分割して処理するツールを作成しました。
ElmoTeacherDecoder/hcpe_shuffle at master · TadaoYamaoka/ElmoTeacherDecoder · GitHub

あと、初期局面のroots.hcpのバリエーションを増やすため、まふ定跡の局面とネットで集めた棋譜の初期局面を追加しています。

あとは、どれだけ精度が上がるか楽しみにして、学習が終わるのを待つだけです。

将棋AIの進捗

検証しているディープラーニングを使った将棋AIは、学習データを増やさないと精度が上げられないため、elmo_for_leanを使ってひたすら学習データを生成中です。

現在、ようやく20億局面くらい。
PCを占有されると困るので、10コアのPCを1台買ってしまいました。
仕組みを作っている間は楽しいですが、精度を上げるフェーズになるとつらいですね・・・

次の電王トーナメントに出るつもりでいますが、上位のソフトに届く可能性は低そうですが、とりあえず頑張ってみるつもりです。

大会のマシンのGPUがしょぼかったらどうにもできないので、Titan Xか1080Tiを複数枚用意してくれないかなぁ。

音声スペクトルモニター(Audio Spectrum Monitor)のバージョンアップ

Androidアプリの音声スペクトルモニター(Audio Spectrum Monitor)をバージョンアップしました。

要望のあったピークホールドの機能を追加しました。

ドラムのチューニングに使いたいという方がいて、瞬間のピッチを保持したいという要望をもらっています。
実装は難しくないですが、UIをどうするかが悩みどころです。
チューニング用途だと音階と周波数Hz表示は必須と思われますが、リアルタイムの表示と2つ表示するとごちゃごちゃしそうで、エレガントなUIをひらめき待ちです。

play.google.com

音声スペクトルモニター(Audio Spectrum Monitor)のバージョンアップ

Androidアプリの音声スペクトルモニター(Audio Spectrum Monitor)をバージョンアップしました。

しばらく将棋AIばかり作っていたので、アプリの開発が止まっていましたm(_ _)m

もらっていた要望のうち、とりあえずGoogleドライブに転送する機能を追加しました。

アプリで保存したファイルはどこに保存されるのか?という質問をよく受けていたのですが、Androidのアプリで保存したファイルはセキュアな領域に保存されるため、他のアプリから直接参照することができません。

代替策として、インテントを使ってオーディオファイルに対応したアプリに転送できるようにしました。
Googleドライブに転送することで、ファイルとして取り出すことができます。


あと、ピークホールドを追加してほしいという要望ももらっていますが、近いうちに対応する予定です。

play.google.com

ディープラーニングを使った将棋AIの作り方

後でちゃんと書く予定

とりあえず以前の記事をリンク
tadaoyamaoka.hatenablog.com

将棋でディープラーニングする その39(ブートストラップ)

前回の日記で、ブートストラップについて少し書いたが、1000万局面では効果がわからなかったので、局面を増やして再度検証した。

ブートストラップ

前回も書いたが、本来の報酬(勝敗)とは別の推定量(探索結果の評価値)を用いてパラメータを更新する手法をブートストラップという。
elmo_for_learnで生成したデータには、局面の探索結果の評価値が含まれているので、バリューネットワークの値をその評価値に近づけるように学習することで、学習の効率を上げることができると思われる。
経験的にブートストラップ手法は、非ブートストラップ手法より性能が良いことが知られている。

ブートストラップ項を加えた損失関数

elmoと同様に、ブートストラップ項の損失には、2確率変数の交差エントロピーを使用する。

バリューネットワークの値をp、探索結果の評価値をシグモイド関数で勝率に変換した値をqとした場合、交差エントロピーは以下の式で表される。
\displaystyle
\begin{eqnarray*}
H(p, q) &=& - \sum_t p(t) \log q(t) \\
 &=& -p \log q - (1 - p) \log(1-q)
\end{eqnarray*}

交差エントロピー偏微分は、
\displaystyle
\frac{\partial H(p, q)}{\partial w} = q - p
となるが、Chainerで実装する場合、backwardの処理をGPUで計算できるように、cudaの処理を記述する必要がある。
技量不足でその部分を実装できなかったため、交差エントロピーを以下のように計算して、微分は計算グラフの処理に任せることにした。

def cross_entropy(p, q):
    return F.mean(-p * F.log(q) - (1 - p) * F.log(1 - q))

このブートストラップ項に係数\lambdaを掛けて、元の損失関数に加える。
損失関数は以下の通りになる。

loss1 = F.mean(F.softmax_cross_entropy(y1, t1, reduce='no') * z)
loss2 = F.sigmoid_cross_entropy(y2, t2)
loss3 = cross_entropy(F.sigmoid(y2), value)
loss = loss1 + loss2 + args.val_lambda * loss3

loss1は指し手予測(policy network)の損失、loss2は勝率予測(value policy)の損失、loss3がブートストラップ項である。

測定結果

ブートストラップなしで2億局面学習したモデルから、ブートストラップなし/ありで、8000万局面を学習して精度を比較した。

train loss1 train loss2 train loss3 test acc.(policy) test acc.(value)
ブートストラップ項なし 0.8883 0.4638 0.4439 0.7651
ブートストラップ項あり 0.8853 0.4741 0.4427 0.4444 0.7658

train loss2(value networkの損失)は、ブートストラップ項のなしの方が減少しているが、test accuracyはブートストラップ項ありの方がわずかに良い。
train loss3はブートストラップ項ありの場合のみ測定しているが、初期から減少を続けており、value networkの予測が評価値に近づいている。

GPSfishとの対局

ブートストラップ項ありで学習したモデルで、GPSfishと対局させた。
f:id:TadaoYamaoka:20170628075612p:plain
GPSfishに勝つことができた。
評価値はGPSfishとほぼ同じ傾向だが、GPSfishより早く評価値が付いている。

ブートストラップ項なしで学習したモデルでは以前と同様に、評価値がGPSfishより遅れて不利を判断しており、勝つことができなかった。
ブートストラップ項を追加することで、バリューネットワークの学習効率が上がることが確かめられた。

これで、ディープラーニングのみでも(GPSfishよりも)強いソフトが作れることが確認できた。
この方法で、さらに学習を進める予定。

将棋でディープラーニングする その38(学習継続中)

前回の日記で、利きを入力特徴に加えることで精度が上がることを確認したので、利きを追加したモデルで、初期値から学習をやり直した。

学習データには、elmo_for_learnで深さ8で生成した、1億5千万局面を使用した。

以前に生成したときは、引き分けの局面も出力していたが、引き分けの報酬を0(または1)として学習すると、精度に悪影響があるため、今回は引き分けは出力しないようにした。

iteration単位

ミニバッチサイズ32で、1000iterationごとのtrain loss、test accuracyは以下の通りとなった。
policy networkとvalue networkをマルチタスク学習しているので、test accuracyはそれぞれ求めている。
f:id:TadaoYamaoka:20170626145033p:plain
train lossが急に上がっている箇所は、棋譜を1000万局面単位で生成してその単位でソートしているため、局面に偏りが出ているためである。

epoch単位

1000万局面を1epochとした場合、epoch単位では以下の通りとなった。
f:id:TadaoYamaoka:20170626145326p:plain

train lossは、まだ減少しているが、ほとんど進まなくなっている。
test accuracy(policy)もまだ増えているが、ほとんど進まなくなっている。
test accuracy(value)は、10epochあたりから0.75から変化していない。

GPSfishと対局

GPSfishと対局すると、GPSfishが劣勢と判断している局面でも優勢と判断しており、かなり遅れてマイナスとなっている。
f:id:TadaoYamaoka:20170626145917p:plain
バリューネットワークが勝敗がはっきりするまで局面を正しく学習できていないようである。

バリューネットワークは、局面の勝率を学習するため、似た局面での勝ち、負けのデータが十分な量必要になる。
1億5千万局面では不十分と思われる。

バッチサイズ変更

勝率は確率的な事象であるため、バッチサイズが小さいと学習できない可能性があるため、バッチサイズを変えて学習してみた。
16epoch目をミニバッチサイズを変えて学習した場合の、train lossとtest accuracyは以下の通りとなった。

ミニバッチサイズ train loss1 train loss2 train loss test acc.(policy) test acc.(value)
b=32 0.9122 0.4522 1.3644 0.4301 0.7569
b=64 0.9102 0.4592 1.3694 0.4362 0.7604
b=128 0.8997 0.4672 1.3669 0.4377 0.7626
b=256 0.8997 0.4683 1.3680 0.4386 0.7620
b=512 0.8998 0.4684 1.3683 0.4380 0.7620
b=1024 0.9049 0.4719 1.3769 0.4371 0.7609

loss1は指し手(policy network)の損失、loss2は勝率予測(value network)の損失を示す。

b=32がtrain lossが一番低くなっているが、test accuracyは一番悪くなった。
b=256がtest accuracy(policy)が最も高い。test accuracy(value)は、b=128が最も高いが、b=256,512もほぼ同じである。
よって、b=256を採用することにする。
学習時間もb=32では1000万局面で1:56:08だったが、b=256にすることで1:15:18と短くなる。

ブートストラップ

elmo_for_learnで生成したデータには、局面の探索結果の評価値が含まれている。
バリューネットワークの値をその評価値に近づけるように学習することで、学習の効率を上げることができないか試した。

このように別の推定量を用いてパラメータを更新する手法をブートストラップと呼び、elmoでも用いられている
また、数手先の探索の評価値を用いるため、TD学習とも呼ばれる。
理論的には理由が明らかにされていないが、経験的にブートストラップ手法は、非ブートストラップ手法より性能が良いことが知られている。

train loss1 train loss2 train loss3 test acc.(policy) test acc.(value)
ブートストラップなし(b=128) 0.9031 0.4620 0.5077 0.4377 0.7628
ブートストラップあり(b=128) 0.9007 0.4744 0.4466 0.4370 0.7621

train loss3はブートストラップ項の損失で、バリューネットワークの値と探索結果の評価値をシグモイド関数で勝率に変換した値との交差エントロピーを示す。
ブートストラップ項の損失には係数\lambda=0.5を掛けている。

train loss3は下がっているので、評価値に近づいているが、test accuracy(value)はほとんど変わっていない。
この測定だけでは、効果があるか不明である。
一旦採用しないで学習を進めることにする。