今回は、ニューラルネットワークの構成を検討する。
ネットワーク構成
ネットワーク構成は、AlphaGoのネットワーク構成を参考にし、13層の畳み込みニューラルネットワーク(DCNN)とする。
位置について精度が要求されるため、プーリング層は使用しない。
入力特徴
9×9の2値画像を特徴数の枚数分入力する。
特徴は以下の通りとする。
特徴 | 枚数 |
自プレイヤーの駒の配置 | 14 |
自プレイヤーの持ち駒 | 38 |
相手プレイヤーの駒の配置 | 14 |
相手プレイヤーの持ち駒 | 38 |
空の配置 | 1 |
持ち駒は、駒ごとに1枚を割り当て、持ち駒の最大枚数分を割り当てる。
持ち駒がある場合は、すべて1の画像とし、持ち駒がない場合はすべて0の画像とする。
入力特徴数の合計は、105枚となる。
他にも、手番や王手かどうか、2歩の位置なども入力特徴とした方が精度があがると思われるが、一旦最低限の特徴のみで検証を行いたい。
出力
指し手の確率を出力する。
指し手は合法手を絞らず、駒ごとの座標に一つのラベルを割り当て、多クラス分類問題として扱う。
どの駒を移動したかは考慮しない。
ラベル数は、駒の種類が14なので、14×9×9=1134となる。
Chainerでの実装
以上のように設計したネットワーク構成、入力特徴、出力をChainerで実装すると以下のようになる。
import chainer from chainer import Chain import chainer.functions as F import chainer.links as L import shogi k = 256 class MyChain(Chain): def __init__(self): super(MyChain, self).__init__( l1=L.Convolution2D(in_channels = None, out_channels = k, ksize = 3, pad = 1), l2=L.Convolution2D(in_channels = k, out_channels = k, ksize = 3, pad = 1), l3=L.Convolution2D(in_channels = k, out_channels = k, ksize = 3, pad = 1), l4=L.Convolution2D(in_channels = k, out_channels = k, ksize = 3, pad = 1), l5=L.Convolution2D(in_channels = k, out_channels = k, ksize = 3, pad = 1), l6=L.Convolution2D(in_channels = k, out_channels = k, ksize = 3, pad = 1), l7=L.Convolution2D(in_channels = k, out_channels = k, ksize = 3, pad = 1), l8=L.Convolution2D(in_channels = k, out_channels = k, ksize = 3, pad = 1), l9=L.Convolution2D(in_channels = k, out_channels = k, ksize = 3, pad = 1), l10=L.Convolution2D(in_channels = k, out_channels = k, ksize = 3, pad = 1), l11=L.Convolution2D(in_channels = k, out_channels = k, ksize = 3, pad = 1), l12=L.Convolution2D(in_channels = k, out_channels = k, ksize = 3, pad = 1), l13=L.Convolution2D(in_channels = k, out_channels = len(shogi.PIECE_TYPES), ksize = 1, nobias = True), l13_2=L.Bias(shape=(9*9*len(shogi.PIECE_TYPES))) ) def __call__(self, x): h1 = F.relu(self.l1(x)) h2 = F.relu(self.l2(h1)) h3 = F.relu(self.l3(h2)) h4 = F.relu(self.l4(h3)) h5 = F.relu(self.l5(h4)) h6 = F.relu(self.l6(h5)) h7 = F.relu(self.l7(h6)) h8 = F.relu(self.l8(h7)) h9 = F.relu(self.l9(h8)) h10 = F.relu(self.l10(h9)) h11 = F.relu(self.l11(h10)) h12 = F.relu(self.l12(h11)) h13 = self.l13(h12) return self.l13_2(F.reshape(h13, (len(h13.data), 9*9*len(shogi.PIECE_TYPES))))
フィルター枚数は、AlphaGoでは192だが、将棋は駒の種類が多いため一旦256とした。
フィルター枚数などのハイパーパラメータは実験により調整が必要である。
次回、作成したニューラルネットワークを使用して、棋譜から学習を行う予定。