ディープラーニングで笑顔を自動検知したい

ディープラーニングで笑顔を自動検知するまでの学習過程を綴っていきます。

数字識別(MNIST)を実践~プログラムその1~

数字識別(MNIST)を実践~プログラムその1~

今回の記事から実際にプログラムを書いていきたいと思います。
今回は学習済みモデルを作成するところまでをやっていきます。

プログラム

プログラム全文が短いのでここに貼り付けてみたいと思います。
このプログラムを実行するとresultフォルダ配下に『CNN.model』という学習済みモデルが作成されます。


・train_mnist_cnn.py

# -*- coding: utf-8 -*-
import chainer
import chainer.functions as F
import chainer.links as L
import chainer.initializers as I
from chainer import training
from chainer.training import extensions

class CNN(chainer.Chain):
    def __init__(self):
        super(CNN, self).__init__(
            # (1)
            conv1=L.Convolution2D(1, 16, 5, 1, 0),
            conv2=L.Convolution2D(16, 32, 5, 1, 0),
            l3=L.Linear(None, 10),
        )

    # (2)
    def __call__(self, x):
        h1 = F.max_pooling_2d(F.relu(self.conv1(x)), ksize=2, stride=2)
        h2 = F.max_pooling_2d(F.relu(self.conv2(h1)), ksize=2, stride=2) 
        y = self.l3(h2)
        return y

def main():

    # (3)
    train, test = chainer.datasets.get_mnist(ndim=3)

    model = L.Classifier(CNN(), lossfun=F.softmax_cross_entropy)
    optimizer = chainer.optimizers.Adam()
    optimizer.setup(model)

    # (4)
    train_iter = chainer.iterators.SerialIterator(train, 100)
    updater    = training.StandardUpdater(train_iter, optimizer)
    trainer    = training.Trainer(updater, (20,'epoch'))

    # (5)
    trainer.extend(extensions.ProgressBar())

    # (6)
    trainer.run()

    # (7)
    modelname = "result" + "/CNN.model"
    print('学習済みモデルを保存: {}'.format(modelname))
    chainer.serializers.save_npz(modelname, model)

if __name__ == '__main__':
    main()

プログラムの解説

(1)各層の処理
今回のネットワークは2層の畳み込みと1層のニューラルネットワークがあります。
conv1:1層目の畳み込み処理
引数の意味は、1=入力の数, 16=フィルタの数, 5=フィルタのサイズ(5x5), 1=ストライド, 0=パディング数

conv2:2層目の畳み込み処理
引数の意味は、16=入力の数, 32=フィルタの数, 5=フィルタのサイズ(5x5ピクセル数), 1=ストライド, 0=パディング数

l3:ニューラルネットの処理
引数の意味は、None=入力の数, 10=出力の数
第1引数は"None"を指定すると自動計算してくれます。
第2引数は今回だと0~9の10個の数字のため10としています。


(2)損失関数
今回"trainer"を使っているのですが、これを使用する場合はChainクラス内部に"__call__"メソッドで損失関数を返す必要があるらしく、
正直よく分かっていないのですが、こういうものなんだという事で今は理解しておきます。

h1:入力xに対してconv1の処理を行ってReLU処理をしてから、フィルタサイズ2x2, ストライド2としてプーリングを行う
h2:入力h1に対してconv2の処理を行ってReLU処理をしてから、フィルタサイズ2x2, ストライド2としてプーリングを行う
y:入力h2に対してl3の処理を行って最終的な値を出力する

前の層の出力が次の層の入力になる様子がハッキリと見てとれますね。


(3)MNISTデータセットの読み込みとニューラルネットワークの設定
get_mnist():データを読み込みます。trainに訓練用データ(データ数60,000)、testにテスト用データ(データ数10,000)が格納される
ndim=3:画像のチャネル数(今回はグレースケールなので1)、画像の横幅、画像の高さ、の3次元のデータにするという設定
optimizers.Adam():最適化アルゴリズムの1つ。よく分かっていないが、パフォーマンスが凄いらしい。。。


(4)Trainerの設定
Trainer:トレーナー。学習を実行するところ。学習とは以下の一連の流れを指す。
1.入力データが各層を伝播していき出力値を計算
2.出力値と教師データから損失(誤差)を計算
3.誤差を伝播させて誤差が小さくなるようにパラメータ(重み)を更新

iterators.SerialIterator(train, 100):100はミニバッチサイズ。1データごとにパラメータ更新を行うと効率が悪いため、ある程度のデータの塊(ミニバッチサイズ)で更新を行う。ミニバッチサイズ100だと、100個のデータの誤差の平均値を基にパラメータを更新する。


(5)進捗バーの表示
学習の進捗状況を表示するためのバーを表示


(6)実行
学習を開始する


(7)モデル出力
学習済みモデルを出力する。今回の場合だとresultフォルダ内(無ければ作成される)にCNN.modelという名称でファイルが作成される。