で Caffe のインストールができたので,MNIST + LeNet で動作確認します.Caffe | LeNet MNIST Tutorial を参考に,MNIST のデータを使って CNN の学習をさせてみることにしました.
以下では,caffe や convert_mnist_data 等の各種実行形式はパスを通してある,相対パスの起点は Caffe を git clone したディレクトリとしてます.
データの準備
data/mnist/get_mnist.sh と mnist/create_mnist.sh をそのまま実行してもよいんですが,MNIST のデータファイル
- train-images-idx3-ubyte
- trainlabels-idx1-ubyte
- t10k-images-idx3-ubyte
- t10k-labels-idx1-ubyte
は MNIST handwritten digit database, Yann LeCun, Corinna Cortes and Chris Burges から既に入手済みだったので,それを利用することにしました.適当なディレクトリを作ってそこに上記4つのファイルを置き,create_mnist.sh の内容を参考にして lmdb 形式に変換します.
$ convert_mnist_data train-images-idx3-ubyte trainlabels-idx1-ubyte mnist_train_lmdb --backend=lmdb $ convert_mnist_data t10k-images-idx3-ubyte t10k-idx1-ubyte mnist_test_lmdb --backend=lmdb
ちなみに,convert_mnist_data コマンドは,lmdbファイルを置くディレクトリが既に存在してるとコアダンプします.
学習の準備
examples/mnist に MNIST の手書き数字認識を convolutional neural net で学習・テストさせる例があるので,それをちょこっといじって実験の準備をします.
- examples/mnist/lenet_train_test.prototxt ネットワークの構成が定義されてる.修正箇所は次の通り.
14c14 < source: "examples/mnist/mnist_train_lmdb" --- > source: "mnist_train_lmdb" 31c31 < source: "examples/mnist/mnist_test_lmdb" --- > source: "mnist_test_lmdb"
- examples/mnist/lenet_solver.prototxt 学習に関するパラメータが定義されてる.修正箇所は次の通り.
2c2 < net: "examples/mnist/lenet_train_test.prototxt" --- > net: "lenet_train_test.prototxt" 23c23 < snapshot_prefix: "examples/mnist/lenet" --- > snapshot_prefix: "lenet"
lenet_train_test.prototxt / lenet_solver.prototxt の定義を読み解くとだいたいこんなん:
- 入力は MNISTの画像(28x28画素,256階調)を 256 で割ったもの
- CNN の構成は 入力から順に,畳み込み+プーリング(conv1 & pool1) ー 畳み込み+プーリング(conv2 & pool2) ー 全結合(ip1 & relu1) ー 出力,というもの.さらに細かく言うと
- conv1: カーネルサイズ 5x5, チャンネル数 20, ストライド 1
- pool1: カーネルサイズ 2x2, ストライド 2, max-pooling
- conv2: チャンネル数が 50 な他は conv1 と同じ
- pool2: pool1 と同じ
- ip1 & relu1: ニューロン数 500, Rectified Linear Unit
- 出力: softmax
- バッチサイズ 100 のSGD,学習係数は 0.01 をベースとして徐々に小さくする,慣性係数 0.9, weight decay 0.0005,学習の繰り返し回数(バッチ単位)は最大1万回
学習させてみる
Ubuntu マシンに Caffe をインストール - まんぼう日記 に書いてる Linux マシンで実験してみました.実行の仕方は次の通り.
$ caffe train --solver=lenet_solver.prototxt
lenet_solver.prototxt の solver_mode を CPU とした場合と GPU とした場合で経過時間を比較してみると,次のようになりました.ちなみに,複数の GPU を搭載したマシンの場合,caffe コマンドの -gpu オプションでどれを使うか選べます.
- CPU(Core i7 5820K 6core 3.3GHz): 約13分
- GPU(GeForce GTX TITAN X): 約20秒
- GPU(Tesla K20c): 約40秒
識別率はいずれの場合もほぼ99%.
比較のため,Theano を使った実験もやってみました.CNN のプログラムは Convolutional Neural Net で CIFAR-10 を識別してみる - まんぼう日記 の時に書いた convnet150821.py ちうやつです.CNN の構成は同じ.重みの初期化や学習の仕方は少し異なります.
$ time THEANO_FLAGS='floatX=float32,device=gpu0' python ex160302.py Using gpu device 0: GeForce GTX TITAN X ### ID: 20160302-175800 ### Conv-Pool-Conv-Pool-ReLu-Softmax Xdim: (1, 28, 28) # W1dim: (20, 5, 5) border_mode: valid # ds1: (2, 2) st1: None H1: 2880 # W2dim: (20, 5, 5) border_mode: valid # ds2: (2, 2) st2: None H2: 320 # H3: 500 ### training: NL = 50000 NV = 10000 batchsize = 100 # eta = 0.01 mu = 0.9 lam = 0.0005 0 0 | 2.3026 87.86 | 2.3026 88.17 1 500 | 2.2947 88.64 | 2.2955 89.36 2 1000 | 0.1645 5.08 | 0.1571 4.72 : 20 10000 | 0.0117 0.33 | 0.0391 1.23 # NT = 10000 20 10000 | 0.0117 0.33 | 0.0391 1.23 | 0.0304 0.94 ### ID: 20160302-175800 real 1m40.598s user 1m8.064s sys 0m32.248s
識別率はこちらも99%でほぼ同じですが,Caffe で20秒だったのがこちらは 100秒.こちらは Theano を利用してたかたかが書いたプログラムなので,比較の仕方がちょっとフェアありませんが(Caffe の方も Python で layer を定義して実験してみるべきでしょう).