人工知能に関する断創録

このブログでは人工知能のさまざまな分野について調査したことをまとめています(更新停止: 2019年12月31日)

ChainerによるCIFAR-10の一般物体認識 (1)

Chainerによる畳み込みニューラルネットワークの実装(2015/10/7)のつづき。今回はMNISTの数字画像認識ではなく、CIFAR-10(2015/10/14)という画像データを使った一般物体認識をやってみた。画像を10個のクラスに分類するタスク。実装にはChainerを使った。

f:id:aidiary:20151014211729p:plain

MNISTは1チャンネルの白黒画像だったけれどCIFAR-10は3チャンネル(RGB)のカラー画像なので少しだけ複雑になる。CIFAR-10(2015/10/14)でも書いたけれどCIFAR-10の提供データは、各画像サンプルがchannel(3チャンネル)、row(32ピクセル)、column(32ピクセル)のフラット形式3*32*32=3072次元ベクトルの形で格納されている。Chainerでは画像を (nsample, channel, height, width) の形式にする必要があるためreshape()して次元を変換している。

    # 画像を (nsample, channel, height, width) の4次元テンソルに変換
    X_train = X_train.reshape((len(X_train), 3, 32, 32))
    X_test = X_test.reshape((len(X_test), 3, 32, 32))

今回は初めてなので畳み込み層とプーリング層が1つずつの簡単な構成で実験した。

INPUT -> (CONV -> RELU) -> POOL -> FC

CONVは畳み込み層、RELUはReLU活性化関数、POOLはプーリング層(max-pooling)、FCは全結合層(隠れ層1つ)である。Chainerでは下のようなコードで簡潔に書ける。modelの方には学習によって変化するパラメータがある層だけまとめられている。プーリング層はパラメータがないのでmodelには含まれない。

    model = chainer.FunctionSet(conv1=F.Convolution2D(3, 32, 3, pad=0),
                                l1=F.Linear(7200, 512),
                                l2=F.Linear(512, 10))

    def forward(x_data, y_data, train=True):
        x, t = chainer.Variable(x_data), chainer.Variable(y_data)
        h = F.max_pooling_2d(F.relu(model.conv1(x)), 2)
        h = F.dropout(F.relu(model.l1(h)), train=train)
        y = model.l2(h)
        if train:
            return F.softmax_cross_entropy(y, t)
        else:
            return F.accuracy(y, t)

畳込み層のconv1=F.Convolution2D(3, 32, 3, pad=0)は、入力が3チャンネル(RGB)、出力の特徴マップが32チャンネル、フィルタ(カーネル)サイズが3x3、パディングサイズが0であることを意味する。

フル結合層は2層からなりl1=F.Linear(7200, 512)は、7200ユニットから512ユニットへ変換する層、l2=F.Linear(512, 10)は512ユニットから10ユニットへ変換する層を意味する。CIFAR-10は10クラスの画像分類なので出力ユニット数は10になる。

畳み込み層ではパディングサイズが0だと出力の特徴マップの画像サイズが入力画像より少し小さくなる。入力画像サイズがW \times WでフィルタがH \times Hだと出力画像サイズは W - 2 \lfloor H/2 \rfloor \times W - 2 \lfloor H/2 \rfloorになる。ここで\lfloor \cdot \rfloorは小数点以下切り下げて整数化する演算。

今回の例だと入力が3x32x32conv1によって32x30x30になる。さらにmax_pooling_2dのウィンドウサイズが2なので画像サイズは半分になって32x15x15になる。これをフラット化してからフル結合層に入力するためフル結合層のユニット数は32x15x15=7200となる。これがl1の入力ユニット数が7200となっている理由。

このユニット数が間違っているとChainerが実行時に正しい値を教えてくれるので、自分で計算するのが面倒なら適当に入れておいてもよいかもしれない(笑)たとえば、適当に1000にしてみると

Actual: 7200 != 1000

というエラーが出る。これは「フル結合層のユニット数は本当は7200なのに1000になっていて違うよ!」という意味。

この構成だとテスト精度で最大67.7%だった。次は畳み込みニューラルネットワークの構成をいろいろ変えたとき精度がどのように変化するか調べてみよう。

参考