SENetの導入

要約

 SENetの構造を導入することによってネットワークの性能が向上した。計算量はやや多くなるが、全体として棋力は向上した。

背景

 山岡さんのブログで将棋ソフトでもSENetの構造が有用であるとの実験結果が示されていた。

 このような簡単な変更かつ僅かな計算量の増加で精度が高くなるなら導入しない手はない。

実装

 実際のコードは

にある通りだが、主要な部分を抜粋する。多少改編も加えている。

 モデルのクラス変数に各ブロックで用いる全結合層を追加。

std::vector<std::vector<torch::nn::Linear>> fc(BLOCK_NUM, std::vector<torch::nn::Linear>(2, nullptr));
for (int32_t i = 0; i < BLOCK_NUM; i++) {
    fc[i][0] = register_module("fc" + std::to_string(i) + "_0",
 torch::nn::Linear(torch::nn::LinearOptions(CHANNEL_NUM, CHANNEL_NUM / REDUCTION).with_bias(false)));
    fc[i][1] = register_module("fc" + std::to_string(i) + "_1",
 torch::nn::Linear(torch::nn::LinearOptions(CHANNEL_NUM / REDUCTION, CHANNEL_NUM).with_bias(false)));
}

 ブロックでの処理において畳み込み2回の後にグローバルアベレージプーリングや全結合層2回の処理を追加。

for (int32_t i = 0; i < BLOCK_NUM; i++) {
    auto t = x;

    x = conv[i][0]->forward(x);
    x = bn[i][0]->forward(x);
    x = torch::relu(x);

    x = conv[i][1]->forward(x);
    x = bn[i][1]->forward(x);

    auto y = torch::avg_pool2d(x, {9, 9});
    y = y.view({-1, CHANNEL_NUM});
    y = fc[i][0]->forward(y);
    y = torch::relu(y);
    y = fc[i][1]->forward(y);
    y = torch::sigmoid(y);
    y = y.view({-1, CHANNEL_NUM, 1, 1});
    x = x * y;

    x = torch::relu(x + t);
}

実験

学習

 floodgateの2015~2018年の棋譜からR2800以上同士の対局を抽出して約1千万局面を教師データとした教師あり学習を行った。Policyの教師は棋譜で指された指し手、Valueの教師は棋譜の最終結果による-1 or 1である。

 上記実装においてREDUCTION = 8とした。これはもともとCNNのチャネル数が64と小さいため16で割るのは過剰ではないかと考えたためである。

 全結合層についてバイアスあり・なしの2通りを実験した。ベースラインとしてSENet構造を入れてないものと比較した。検証損失の推移を以下に示す。

f:id:tokumini:20190529104048p:plainf:id:tokumini:20190529104054p:plain
左:Policy損失 右:Value損失

 どれも38エポックを経過した段階で最も損失和が低くなっており、その時点での値を以下に示す。

モデル Policy損失 Value損失 学習時間の比
baseline 1.732598 0.409436 1
SENet 1.707092 0.402247 1.138
SENet with bias 1.710603 0.400820 1.149

 バイアスあり・なしのいずれにおいてもベースラインより低い損失となった。ベースラインのモデルが10ブロック・64チャネルという比較的小さなネットワークのためか、SENet構造を入れることによる学習時間の増加は13%~14%と大きめになっている。学習に比べて対局時にはネットワーク以外の処理も含まれるためNPSの低下はこれよりも小さいはずであり、影響は少ないと思われる。

検証対局

 それぞれのモデルを用いて技巧2(深さ1)と1手1秒で200局対局を行った。

モデル 技巧2に対する勝率 Eloレート差
baseline 48.0% -13.9
SENet 74.8% +188.5
SENet with bias 65.8% +113.3

 SENet構造を導入することで探索速度の低下を補ってあまりある程の棋力向上が見られた。全結合層のバイアスはないものの方が高い勝率となったが、ここまで大きな差がつくのは損失の違いがわずかであったことからすると意外な結果である。偶然の影響が大きそうな気はするが、勝率だけでなく損失も悪くないためとりあえずバイアスなしのSENetで強化学習を試してみることとする。結果はいずれにここに追記する。

 以下2019/06/02追記

強化学習

 バイアスなしのSENetを用いてAlphaZero方式の強化学習を試した。

f:id:tokumini:20190602163454p:plainf:id:tokumini:20190602163457p:plain
左:Policy損失 右:Value損失

 検証損失はベースラインよりも低い値となった。また技巧2(深さ5)と1手1秒で300局対局させた結果も

モデル 技巧2に対する勝率 Eloレート差
baseline 56.0% +41.9
SENet 72.0% +164.1

となりやや性能が上がった。