【将棋AI】「将棋AIで学ぶディープラーニング」を読む♪～モデルを変更する

<img width="200" style="float: left;" alt="将棋AIで学ぶディープラーニング" src="https://qiita-image-store.s3.amazonaws.com/0/233744/ded117b9-37c7-1b41-033d-960e63ca5fe1.jpeg">
第十三夜は、Networkモデルを変更して、より強い将棋AIに挑戦します。
###やったこと
（１）Resnetで学習
（２）対戦してみる
（３）より強い将棋AIを目指す
###（１）Resnetで学習
本書ではハイパーパラメータの調整ということで、フィルター枚数の変更、ミニバッチサイズの変更、層数の変更、BatchNormalization、そして最適化手法の変更を実施して結果を示しています。
さらに、resnetが層が深くても収束させられるモデルであることを解説し、ブロックを５層と１０層で学習して傾向を示しています。
ということで、ウワンもこのResnetの５層モデルで学習を実施して最初のモデルとの違いを見たいと思います。
※ここでは一応モデルを変更して学習させるということを主目的に実施します
ResnetのNetworkはググるといくつか出てきますが、やはり少し複雑です。本書のモデルはとても教育的なコードで分かり易いと思います。

```py
﻿from chainer import Chain
import chainer.functions as F
import chainer.links as L
from pydlshogi.common import *

ch = 192
fcl = 256

class Block(Chain):
    def __init__(self):
        super(Block, self).__init__()
        with self.init_scope():
            self.conv1 = L.Convolution2D(in_channels = ch, out_channels = ch, ksize = 3, pad = 1, nobias=True)
            self.bn1 = L.BatchNormalization(ch)
            self.conv2 = L.Convolution2D(in_channels = ch, out_channels = ch, ksize = 3, pad = 1, nobias=True)
            self.bn2 = L.BatchNormalization(ch)
    def __call__(self, x):
        h1 = F.relu(self.bn1(self.conv1(x)))
        h2 = self.bn2(self.conv2(h1))
        return F.relu(x + h2)

class PolicyValueResnet(Chain):
    def __init__(self, blocks = 5):
        super(PolicyValueResnet, self).__init__()
        self.blocks = blocks
        with self.init_scope():
            self.l1=L.Convolution2D(in_channels = 104, out_channels = ch, ksize = 3, pad = 1)
            for i in range(1, blocks):
                self.add_link('b{}'.format(i), Block())
            # policy network
            self.policy=L.Convolution2D(in_channels = ch, out_channels = MOVE_DIRECTION_LABEL_NUM, ksize = 1, nobias = True)
            self.policy_bias=L.Bias(shape=(9*9*MOVE_DIRECTION_LABEL_NUM))
            # value network
            self.value1=L.Convolution2D(in_channels = ch, out_channels = MOVE_DIRECTION_LABEL_NUM, ksize = 1)
            self.value1_bn = L.BatchNormalization(MOVE_DIRECTION_LABEL_NUM)
            self.value2=L.Linear(9*9*MOVE_DIRECTION_LABEL_NUM, fcl)
            self.value3=L.Linear(fcl, 1)

    def __call__(self, x):
        h = F.relu(self.l1(x))
        for i in range(1, self.blocks):
            h = self['b{}'.format(i)](h)
        # policy network
        h_policy = self.policy(h)
        u_policy = self.policy_bias(F.reshape(h_policy, (-1, 9*9*MOVE_DIRECTION_LABEL_NUM)))
        # value network
        h_value = F.relu(self.value1_bn(self.value1(h)))
        h_value = F.relu(self.value2(h_value))
        u_value = self.value3(h_value)
        return u_policy, u_value
```
以下のblocks=5を変更すればブロック数を自由に変更できます。
※ここでは収束時間が早い５層とします

```py
    def __init__(self, blocks = 5):
```
また、このモデルでは、BatchNormalizationも利用しています。
図で表すと以下のように書けます。
![resnet.jpg](https://qiita-image-store.s3.amazonaws.com/0/233744/f97fd0e2-2792-e9d2-59c3-40ed7774ddf3.jpeg)

早速学習してみます。学習は以前のモデルと同じデータを学習します。


```
>python train_policy_value_resnet.py kifulist3000_train.txt kifulist3000_test.txt --eval_interval 1000
2018/09/04 21:35:05     INFO    read kifu start
2018/09/04 21:35:25     INFO    load train pickle
2018/09/04 21:35:27     INFO    load test pickle
2018/09/04 21:35:27     INFO    read kifu end
2018/09/04 21:35:27     INFO    train position num = 1892246
2018/09/04 21:35:27     INFO    test position num = 208704
2018/09/04 21:35:27     INFO    start training
2018/09/04 21:36:00     INFO    epoch = 1, iteration = 1000, loss = 6.252685, accuracy = 0.171875, 0.60546875
2018/09/04 21:36:31     INFO    epoch = 1, iteration = 2000, loss = 5.033235, accuracy = 0.17773438, 0.5859375
2018/09/04 21:37:01     INFO    epoch = 1, iteration = 3000, loss = 4.5309515, accuracy = 0.25585938, 0.6035156
。。。
2018/09/04 22:07:20     INFO    epoch = 1, iteration = 59132, train loss avr = 3.3427236, test accuracy = 0.34475157, 0.67265373
2018/09/04 22:07:20     INFO    save the model
2018/09/04 22:07:20     INFO    save the optimizer
。。。
2018/09/05 02:55:51     INFO    epoch = 10, iteration = 591320, train loss avr = 1.9026536, test accuracy = 0.40383473, 0.6531782
2018/09/05 02:55:51     INFO    save the model
2018/09/05 02:55:52     INFO    save the optimizer
。。。
2018/09/06 01:51:48     INFO    epoch = 18, iteration = 1292000, loss = 1.8666146, accuracy = 0.390625, 0.6816406
2018/09/06 01:52:19     INFO    epoch = 18, iteration = 1293000, loss = 1.8751647, accuracy = 0.43945312, 0.6816406
2018/09/06 01:52:49     INFO    epoch = 18, iteration = 1294000, loss = 1.8839896, accuracy = 0.46484375, 0.6933594
2018/09/06 01:53:19     INFO    epoch = 18, iteration = 1295000, loss = 1.8709311, accuracy = 0.45507812, 0.6953125
2018/09/06 01:53:23     INFO    validate test data
2018/09/06 01:55:48     INFO    epoch = 18, iteration = 1295110, train loss avr = 1.8446575860697083, test accuracy = 0.4195995, 0.6717752
```
![figure_1-34resnet_2016_2017.png](https://qiita-image-store.s3.amazonaws.com/0/233744/3d25aaee-5591-27bb-e5f2-66922ef8e1bd.png)
以下山岡さんの最近の一致率と比較してみると、案外いい線いってるように見える。

| － | 方策（一致率） | 価値（一致率） |
|:-:|:-:|:-:|
| Resnet５layer| 0.4195995| 0.6717752|
| yamaoka19| 0.4090266|0.68762606|
| yamaoka38|0.437221587|0.706173778|
注意；yamaoka19と38のデータは異なるデータに対する方策の一致率と価値の一致率
【参考】
・[将棋AIの進捗 その25(自己対局による強化学習の経過)](http://tadaoyamaoka.hatenablog.com/entry/2018/08/26/221248)
###（２）対戦してみる
ということで、対戦してみます。ここでは昨夜のmcts_playerを使います。
結果は。。。惨敗。。[Lesserkai（レイティング７００位）](http://www.uuunuuun.com/)に全く歯が立ちません。ちなみにパラメータは、Temperature＝１００、Depth＝３００です。
![resnetvslesserkai.jpg](https://qiita-image-store.s3.amazonaws.com/0/233744/0e2bcad6-a915-0a15-4c30-fbdd4aeb2748.jpeg)
将棋が下手なウワンには何が悪いか本当のところはわかりませんが、とにかくいいところまで追いつめても、最後のところで積み切れずに負けてしまいます。。。。
###（３）より強い将棋AIを目指す
まず、当初のモデルはどこまで強くなったかというと、上記とほぼ同じ学習、つまりfloodgateの２０１６年と２０１７年の棋譜で学習したものは以下の一致率になっています。
![figure_1-34_3000_2016-2017.png](https://qiita-image-store.s3.amazonaws.com/0/233744/189a176a-3d90-4e3a-2dc6-2392c3f5ae15.png)
はっきり言って、先ほどのResnetの場合とほとんど同じような学習曲線になっています。
表にすると以下のとおりです。

| － | 方策（一致率） | 価値（一致率） |
|:-:|:-:|:-:|
| １３layer| 0.4204578| 0.67033803|
| Resnet５layer| 0.4195995| 0.6717752|
| yamaoka19| 0.4090266|0.68762606|
| yamaoka38|0.437221587|0.706173778|

しかし、学習したものは少し異なっているようです。
すなわち、こちらの方が断然強いんです。
以下のようにLesserKaiに８：２で勝っています。
※最後は大ゴマ渡して勝手に投了しちゃってますが、。。
ちなみにパラメータは上記のResnetと同じTemperature＝１００、Depth＝３００です。
![lesserkaivs13.jpg](https://qiita-image-store.s3.amazonaws.com/0/233744/35a59dc2-143e-13a0-2543-baaec688c8e6.jpeg)
そして、Temperature＝７５、Depth＝１０００だと、[Gikouの（•レベル1（読みの深さ1手）: 将棋倶楽部24の８級相当 (R 800程度)](https://github.com/gikou-official/Gikou)といい勝負。。。もちろん持ち時間多めですが、。。
![GikouvsLayer13.jpg](https://qiita-image-store.s3.amazonaws.com/0/233744/356505b7-a665-5643-e390-833ebd8dde4a.jpeg)
まだまだ将棋AIのモデルは未知数です。
問題は大きく以下二点です。
①特にNetworkに何をどの程度の層で使えばより最適化という大きな問題があります。それはそれを支えるマシンパワーとのバランスもとれていなければなりません。AlphaGoやAlphazeroと同じようなロジックにはできますが、彼らはTPUという計算基盤をフル回転してその威力を最大化した結果でした。
普通のマシン基盤で使えるモデルはまた違ったモデルが最適になる可能性もあると考えています。
②そもそも学習したいが適当な棋譜とはどんなものか、そしてそれを大量に用意するにはどうすべきか。やはり強化学習をする以外に強化できる可能性がないように思う。つまり、将棋AIでは強化学習は当然の帰結である。たぶんこれは将棋に限ったことではなく、最初は人間のまねをしてルールというかドメインの性質を学習して、最後は強化学習という自己学習でより上を目指す。その場合もやはりマシン基盤が重要な役割となる。

###まとめ
・より強い将棋AIを目指してResnet５層で学習した
・得られた一致率はあまり変わらないが、Resnet５層は弱かった
・従来の１３層のモデルが少し強くなった

・さらに強い将棋AIのモデルを作れる可能性がある