その3の続き
自己対局パイプライン
自己対局パイプラインは、3つの主要な部分から構成される。
- 最適化
- 評価
- 自己対局
これらは並行で実行される。
最適化
- ミニバッチサイズ:2,048 (32バッチずつ別々のGPUで実行)
- ミニバッチデータは直近50万の自己対局のすべての局面からランダムでサンプリング
- モーメントありのSGDで最適化(モメンタムパラメータ=0.9)
- 学習率は以下の通り徐々に下げる
1000ステップ | 学習率 |
0-400 | |
400-600 | |
>600 |
損失関数を式にすると以下の通り
zは勝敗(-1,1)、vはvalue、はモンテカルロ木探索で求めた局面の遷移確率、
はpolicyの遷移確率、
はネットワークのパラメータの2乗ノルム
- 自己対局1,000回ごとにチェックポイントを設ける
- チェックポイントで次の自己対局で使用するか評価を行う
評価
自己対局
- 各ゲームの最初の30手は温度
に設定する(訪問回数の応じた確率で着手し、局面にバリエーションを持たせる)
- 残りの手は、温度
に設定する
- ルートノードの事前確率にディリクレノイズを加える
- 具体的には、
- このノイズは、全ての手を試すために行うが、探索することで悪手は選択されなくなる
- 計算資源を節約するため、明らかに負けの場合投了する
- 閾値は誤認率を5%以下に保つように自動的に決定する
- 誤認率を測定するため10%のゲームは終局までプレイする
将棋AIに応用する際の考察
損失関数について
policyの交差エントロピーは、式では教師データの指し手ではなく、遷移確率を使用していますが、温度パラメータを0にして自己対局しているので、実際は打ち手のみを学習することになるので、教師データとして打ち手をone hotベクトルとしたsoftmax交差エントロピーを使っていると思われます。
valueの損失には平均二乗誤差が使われています。
出力の活性化関数がtanhの場合は、交差エントロピーは負の値に使えないので、平均二乗誤差を使用していると思われます。
報酬が(-1,1)の単位スケールなのでvalueの平均二乗誤差とpolicyの交差エントロピーと同じ重みにするのは合理的だと、書かれていましたがちょっと意味が分かりませんでした。
なお、将棋AIでは、評価関数の出力にsigmoidを使用して、損失には交差エントロピーを使うのが主流になっています。
温度パラメータについて
局面のバリエーションを増やすために、自己対局の最初30手は温度パラメータが調整されています。
将棋AIでは、初期局面集を使って局面バリエーションを増やすことが行われています。
初期局面集の質が良ければその方がバリエーションを増やすには良いと思います。
初期局面集から開始して温度パラメータ調整ありで、数手を指すのが良いかもしれません。
残りの手は、温度パラメータを0にして最大訪問回数のノードを選択しています。
それではpolicyが予測する限られた手以外を探索しなくなるので、ルート局面のみノイズが加えられています。
policyは読み抜けをなくすこと重要なので、ノイズを加えることで対策しているようです。
ルート局面以外にもノイズを加えると探索の幅が広がりすぎるので、ルート局面のみに限定しています。
ノイズを加えることで、ついでにある程度打ち手にランダム性を加えることもできます。
ディリクレノイズについて、K次元のディリクレ分布は、
で表されるので、出力ラベル数を次元としたディリクレ分布に従って生成した値をノイズに加えるということだと思います。
(合っているか自信がありません。間違っていたら教えてください。)
2017/10/24 追記
ディリクレ分布について、グラフにして確かめてみた。
Dir(0.03)をα=0.03の対称ディリクレ分布と解釈すると、2次元の場合グラフは以下のようになる。
alpha = [0.03 0.03]; x1 = linspace(0,1,101); x2 = linspace(0,1,101); [X1, X2] = ndgrid(x1, x2); bad = (X1+X2 > 1 | X1+X2 < 0.98); X1(bad) = NaN; X2(bad) = NaN; betaConst = exp(sum(gammaln(alpha))-gammaln(sum(alpha))); F = (X1.^(alpha(1)-1) .* X2.^(alpha(2)-1)) / betaConst; figure, surf(X1,X2,F,'EdgeColor','none'); xlabel('x1'); ylabel('x2'); zlabel('f(x1,x2)');
参考:
http://jp.mathworks.com/matlabcentral/newsreader/view_thread/139363
また、以下のようなスクリプトで5次元のディリクレ分布に従ってランダムに値を10個生成すると、以下のような値が生成された。
function r = drchrnd(a,n) % take a sample from a dirichlet distribution p = length(a); r = gamrnd(repmat(a,n,1),1,n,p); r = r ./ repmat(sum(r,2),1,p); endfunction A = drchrnd([0.03 0.03 0.03 0.03 0.03], 10)
参考:
To Generate Random Numbers from a Dirichlet Distribution | Yi Wang's Tech Notes
生成された値
6.9672e-006 7.3486e-014 1.0742e-012 1.1276e-047 9.9999e-001 5.5256e-009 1.5200e-037 9.9999e-001 6.5353e-006 4.2202e-034 9.9999e-001 5.9592e-006 6.0206e-009 4.5226e-014 2.7251e-012 2.3452e-025 5.0914e-011 9.9862e-018 1.0000e+000 2.7700e-043 1.0641e-033 2.6900e-015 3.5634e-008 4.1919e-001 5.8081e-001 1.5973e-010 2.2561e-010 1.8230e-023 6.8685e-045 1.0000e+000 1.2859e-044 7.1633e-009 8.1942e-005 2.2902e-019 9.9992e-001 7.8554e-001 7.7956e-018 1.4490e-005 2.1445e-001 3.6593e-023 1.8477e-006 6.7389e-014 9.9992e-001 2.3746e-005 5.3420e-005 3.8418e-039 2.9569e-011 9.9991e-001 9.9550e-025 9.3844e-005
以上の結果から、α=0.03のディリクレ分布はどれか一つの要素が1になり、他が0になるような分布になっていることがわかる。
つまり、ルートノードではどれか一つの手をランダムで選びやすくしている。
実装上は、ディリクレ分布を計算しなくてもランダムで1手を選んでその手のみη=1にしても問題ないかもしれない。