Chainer:CIFAR-10のカラー画像に畳み込みを入れてみよう


2017年 05月 10日

画像ファイルを学習させるには、中間層が全部、単純至極な全結合層ではだめらしい。
世の中では、畳み込み層というのを使い、通常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))
たったこれだけの変更で、畳み込みができるようになり、精度が上昇するであろうか? 結果は次回に示す。