Edited at

【将棋AI】「将棋AIで学ぶディープラーニング」を読む♪~Networkモデルの拡張;モデュレーション

将棋AIで学ぶディープラーニング

第十八夜は、少しモデルをいじってみた。


やったこと

(1)今までのモデルで総当たり戦をやってみた

(2)Resnetの繰り返しを2層から3層にしてみた

(3)さらなるNetworkモデルの拡張できるように層をモデュレートしてみた


(1)今までのモデルで総当たり戦をやってみた

Networkモデルとして、Resnetの23層と13層を追加しました。これでResnetにおける層の深さの比較ができます。今回の記事全体のモデルは以下のとおりです。

名称
loss
一致率(方策)
一致率(価値)
備考

policy
1.682677
0.4226734
-
方策ネットワークのみ

Policy_Value;Layer13
2.016
0.4204578
0.67033803
13層の方策・価値ネットワークでMCTS

ResnetSimple40※
2.29075
0.4325099
0.6906338
Resnet20block43層

ResnetSimple20 
2.308355
0.4326057
0.6941468
Resnet10block23層

ResnetSimple10
2.360802
0.42507267
0.6948055
Resnet5block13層

ResnetTry30
2.27104
0.43431032
0.6986858
ResnetTri10block33層

ResnetVGGLike5
2.279315
0.43526843
0.69514084
ResnetVGGLike5block19層

※前回の対戦と使用したパラメータが異なっています

下二つのモデルを除く結果は以下のようになりました。つまり、ここまでは層が深いほどよさそうです。が、Resnet無しが頑張っています。

S102040MctsPolLkai.jpg


(2)Resnetの繰り返しを2層から3層にしてみた

モデルは以下のとおり、今までBlockとして二層ずつ追加したものを三層ずつ追加するように変更してみました。

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)
self.conv2 = L.Convolution2D(in_channels = ch, out_channels = ch, ksize = 3, pad = 1)
self.conv3 = L.Convolution2D(in_channels = ch, out_channels = ch, ksize = 3, pad = 1)

def __call__(self, x):
h1 = F.relu(self.conv1(x))
h2 = self.conv2(h1)
h3 = self.conv3(h2)
return F.relu(x+h3)

10Blockにしたので、モデルは全部で33層になります。

上記の結果もあるので、効果としてResnetとNormalとの中間の効果が出るといいなぁ~という程度です。

一致率等は上記の表のとおりです。

そして、結果は以下のようになりました。

※記事書いていて気が付いたけど、これh2 = F.relu(self.conv2(h1))のミスですね

Try3sen.jpg

Try3sen2.jpg

ミスはあったが、とりあえず、層の深さに依存して強さの順位となりました。


(3)さらなるNetworkモデルの拡張できるように層をモデュレートしてみた

これらの延長として簡単にできるNetworkモデルの拡張をやってみた。本当はVGGNetに近づけたいが、テンソル計算の辻褄をつけるのが難しいのでとりあえずの拡張です。

【参考】

Chainerにおけるグラフ構造をループで書いてみる。

ch = 192

fcl = 256
class RoopBlock(Chain):
def __init__(self,n_in,n_out,stride=1):
super(RoopBlock,self).__init__()
with self.init_scope():
self.conv1 = L.Convolution2D(in_channels = n_in, out_channels = n_out, ksize = 3, pad = 1)
self.conv2 = L.Convolution2D(in_channels = n_out, out_channels = n_out, ksize = 3, pad = 1)
self.conv3 = L.Convolution2D(in_channels = n_out, out_channels = n_in, ksize = 3, pad = 1)
def __call__(self,x):
h = F.relu(self.conv1(x))
h = F.relu(self.conv2(h))
h = F.relu(self.conv3(h)+x)
return h

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)
links = [("root0",RoopBlock(ch,ch))]
n_in = ch
n_out = 256
for index in range(1,5,1):
links += [("root{}".format(index),RoopBlock(n_in,n_out))]
n_in *= 1
n_out *= 1
for link in links:
self.add_link(*link)
self.forward = links
# policy network
self.policy=L.Convolution2D(in_channels = n_in, 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 = n_in, out_channels = MOVE_DIRECTION_LABEL_NUM, ksize = 1)
self.value2=L.Linear(9*9*MOVE_DIRECTION_LABEL_NUM, fcl)
self.value3=L.Linear(fcl, 1)

def __call__(self, x):
x = F.relu(self.l1(x))
for name,func in self.forward:
x = func(x)
# policy network
u_policy = self.policy(x)
u_policy = self.policy_bias(F.reshape(u_policy, (-1, 9*9*MOVE_DIRECTION_LABEL_NUM)))
# value network
h_value = F.relu(self.value1(x))
h_value = F.relu(self.value2(h_value))
u_value = self.value3(h_value)
return u_policy, u_value

そして、強さは以下のようにResnetS40と4:1:5とほぼ互角という結果であった。

VGGvsS40.jpg

このモデルは層も19層であり、それほど深くもなく、かつ1epoch当たりの時間は、以下のとおり予測どおりである。

model
time/epoch

S43
57:10
43層

VGGL19
45:19
19層

S23
37:59
23層

S13
30:30
13層


まとめ

・層は深いほど強い

・同じ層を重ねるより、モデュレーションをかけた方が強くなる可能性がある

・まだまだNetworkモデルを工夫できる可能性がある