画像ファイルを学習させるには、中間層が全部、単純至極な全結合層ではだめらしい。
世の中では、畳み込み層というのを使い、通常3×3のフィルタを用いて畳み込みニューラルネットワークを作るとあちこちで見かけた。
ということで、早速やってみよう。
というか、ネットで探してみた。
すると、Chainerでは、Convolution2Dなるものが用意されていて、これを使って中間層を増やしていけば良いらしい。
Chainerのマニュアルによると、引数は以下のようになっていて、急にこんなにたくさん理解できない(笑)
class chainer.links.
Convolution2D
(in_channels,
out_channels,
ksize,
stride=1,
pad=0,
wscale=1,
bias=0,
nobias=False,
use_cudnn=True,
initialW=None,
initial_bias=None,
deterministic=False)肝心なのは、最初の3つのパラメータのようだ。
in_channels : 入力チャネル数
out_channels : 出力チャネル数
ksize : フィルタのサイズ
入力チャネル数は、画像データがRGBの3チャンネルだから3と入れても良いのだが、Noneと指定すれば、入力データからチャネル数を自動で決めてくれるらしい。無駄な指定(努力)はバグの元、横着をしよう。
出力チャネル数は、まあ適当な値を設定しよう。
フィルタのサイズは、もっとも一般的な 3×3 のフィルタを指定するので、3になる。
中間層が1つ増えたので、クラスの中の実行メソッド(?) __call(self,x)を1つ増やした。
さらに、クラスの名前を、CNN (convolutional neural network) に変更したの、modelを作るときのクラス名がCNNに変わった。
CNNを1層増やすためにした変更は、全部でたったの3行である。クラス名はついでなので、実質2行の変更で畳み込みネットワークを使えるようになる。
なんだか、嘘のように簡単だ。
とりあえず、CNNクラスを示す。
# Network definition
class CNN(chainer.Chain):
def __init__(self, n_units, n_out):
super(CNN, self).__init__(
conv1=L.Convolution2D(None, 48, 3), # 追加行
l1=L.Linear(None, n_units[0]), # n_in -> n_units[0]
l2=L.Linear(None, n_units[1]), # n_units[0] -> n_units[1]
l3=L.Linear(None, n_out), # n_units[1] -> n_out
)
def __call__(self, x):
c1 = F.relu(self.conv1(x)) # 追加行
h1 = F.relu(self.l1(c1))
h2 = F.relu(self.l2(h1))
return self.l3(h2)
modelを作るところが、ちょっと変わった。
model = L.Classifier(CNN(args.units, 10))
たったこれだけの変更で、畳み込みができるようになり、精度が上昇するであろうか?
結果は次回に示す。