【Caffe】モデルをダウンロードして利用する
他の人が作成し、アップロードしているモデルを利用する。
今回は手始めにVGG16のネットワークとモデルをダウンロードし、Caltech101のデータをかけてみる
1.ネットワーク定義ファイルのダウンロード
多くの研究結果がModel Zooで公開されており、GitHub Gistでダウンロードできる(Caffe内のダウンロード専用のスクリプトを使う)
まず、Model Zoo(Model Zoo · BVLC/caffe Wiki · GitHub)でVGG16のページを探し、readme.mdのGist IDを確認する
ILSVRC-2014 model (VGG team) with 16 weight layers · GitHub
IDが確認できたらスクリプトを使ってダウンロードする。
※以下、$WORKのフォルダで作業するものとする
$ cd $WORK $ $CAFFE_HOME/scripts/download_model_from_gist.sh 211839e770f7b538e2d8 . $ cd 211839e770f7b538e2d8
さらに、readme.mdからモデルファイルの場所を確認し、ダウンロードする
$ wget http://www.robots.ox.ac.uk/~vgg/software/very_deep/caffe/VGG_ILSVRC_16_layers.caffemodel
2.スクリプトの実行
pythonのスクリプトを実行して識別にかける。モデルの定義ファイルと学習済みモデルをマニュアルで指定する必要がある。今回、meanファイルは公開されていなかったので、使わなくていいと判断(使わない場合は''とするらしい)
cp $CAFFE_HOME/python/classify.py . ./classify.py --raw_scale 224 --model_def VGG_ILSVRC_16_layers_deploy.prototxt --pretrained_model VGG_ILSVRC_16_layers.caffemodel --mean_file '' $CAFFE_HOME/data/101_ObjectCategories/airplanes/image_0001.jpg result.npy
result.npyが出力されるため、以前(【Caffe】物体認識のサンプルを動かす - いつもの作業の備忘録)作成したshow_result.pyを使って結果を見てみる。
python show_result.py $CAFFE_HOME/data/ilsvrc12/synset_words.txt result.npy
結果は以下のようになり、確かに軍用機がトップに来ている。
#1 | n04552348 warplane, military plane | 87.0% #2 | n04266014 space shuttle | 2.1% #3 | n04008634 projectile, missile | 1.7%
※参考
https://github.com/BVLC/caffe/wiki/Model-Zoo
https://gist.github.com/ksimonyan/211839e770f7b538e2d8#file-readme-md
【Caffe】Fine Tuningする
以下のサイトの後半に書かれているファインチューニングの手順を実行
Caffeで手軽に画像分類 - Yahoo! JAPAN Tech Blog
1.データ準備
学習時には3つのデータが必要。
- train.txt:ネットワークのパラメタ(重み)を学習するデータ
- val.txt :学習時に定期的にテストし、過学習を起こしていないかチェックするデータ
- test.txt :本番テスト用データ
上記はすべて画像ファイルパスと正解クラスがタブ区切りとなったデータ。
$ cat train.txt accordion/image_0001.jpg 0 accordion/image_0002.jpg 0 :
train.txtとtest.txtはせっかくなので、前回利用した20枚の学習データ、8枚の評価データと同じものを準備。val.txtは新しく10枚ほど調達
2.平均画像生成
Caffeでは平均画像をあらかじめ引き算した画像を利用するらしい。背景が決まっているときなどは特に有効そう。平均画像を使わなくても学習できるらしいが、今回は平均画像を利用する。
Caffeの仕様が変わって元サイト通りにやると Incorrect data field size というエラーが出てコアダンプするため以下のように変更
$ $CAFFE_HOME/build/tools/convert_imageset.bin -gray -resize_width 256 -resize_height 256 $CAFFE_HOME/data/101_ObjectCategories/ train.txt caltech101_train_leveldb $ $CAFFE_HOME/build/tools/convert_imageset.bin -gray -resize_width 256 -resize_height 256 $CAFFE_HOME/data/101_ObjectCategories/ val.txt caltech101_val_leveldb $ $CAFFE_HOME/build/tools/compute_image_mean.bin caltech101_train_leveldb/ caltech101_mean.binaryproto
3.モデルファイルの編集
もともとbvlc_reference_caffenetで使っていたモデルを元にFine Tuningを実施するため、元のモデルをコピーし、ネットワークの名前を変更する
$ cd $CAFFE_HOME $ cp $CAFFE_HOME/models/bvlc_reference_caffenet/*.prototxt $CAFFE_HOME $ sed -i -e 's/fc8/fc8ft/g' train_val.prototxt deploy.prototxt
ファイル編集
solver.prototxt
#変更前 net: "models/bvlc_reference_caffenet/train_val.prototxt" test_iter: 1000 test_interval: 1000 base_lr: 0.01 lr_policy: "step" gamma: 0.1 stepsize: 100000 display: 20 max_iter: 450000 momentum: 0.9 weight_decay: 0.0005 snapshot: 10000 snapshot_prefix: "models/bvlc_reference_caffenet/caffenet_train" solver_mode: GPU ↓ #変更後 net: "train_val.prototxt" test_iter: 1000 test_interval: 1000 base_lr: 0.001 lr_policy: "step" gamma: 0.1 stepsize: 100000 display: 20 max_iter: 450000 momentum: 0.9 weight_decay: 0.0005 snapshot: 10000 snapshot_prefix: "snapshot" solver_mode: GPU
train_val.prototxt
#変更前 transform_param { mirror: true crop_size: 227 mean_file: "data/ilsvrc12/imagenet_mean.binaryproto" } ↓ #変更後 transform_param { mirror: true crop_size: 227 mean_file: "caltech101_mean.binaryproto" }
#変更前 data_param { source: "examples/imagenet/ilsvrc12_train_lmdb" batch_size: 256 backend: LMDB } ↓ #変更後 data_param { source: "caltech101_train_leveldb" batch_size: 256 backend: LMDB }
#変更前 transform_param { mirror: false crop_size: 227 mean_file: "data/ilsvrc12/imagenet_mean.binaryproto" } ↓ #変更後 transform_param { mirror: false crop_size: 227 mean_file: "caltech101_mean.binaryproto" }
#変更前 data_param { source: "examples/imagenet/ilsvrc12_val_lmdb" batch_size: 50 backend: LMDB } ↓ #変更後 data_param { source: "caltech101_val_leveldb" batch_size: 50 backend: LMDB }
#変更前 inner_product_param { num_output: 1000 weight_filler { type: "gaussian" std: 0.01 } bias_filler { type: "constant" value: 0 } } ↓ #変更後 inner_product_param { num_output: 102 weight_filler { type: "gaussian" std: 0.01 } bias_filler { type: "constant" value: 0 } }
deploy.prototxt
#変更前 name: "CaffeNet" layer { name: "data" type: "Input" top: "data" input_param { shape: { dim: 10 dim: 3 dim: 227 dim: 227 } } } ↓ #変更後 name: "CaffeNet" layer { name: "data" type: "Input" top: "data" input_param { shape: { dim: 10 dim: 3 dim: 256 dim: 256 } } }
#変更前 layer { name: "fc8ft" type: "InnerProduct" bottom: "fc7" top: "fc8ft" inner_product_param { num_output: 1000 } } ↓ #変更後 layer { name: "fc8ft" type: "InnerProduct" bottom: "fc7" top: "fc8ft" inner_product_param { num_output: 102 } }
4.学習実行
$ $CAFFE_HOME/build/tools/caffe train -solver solver.prototxt
結果
I0304 23:01:09.303612 5094 solver.cpp:244] Train net output #0: loss = 0.00736864 (* 1 = 0.00736864 loss) I0304 23:01:09.303623 5094 sgd_solver.cpp:106] Iteration 5920, lr = 0.001 I0304 23:01:14.809386 5094 solver.cpp:228] Iteration 5940, loss = 0.0244083 I0304 23:01:14.809422 5094 solver.cpp:244] Train net output #0: loss = 0.0244083 (* 1 = 0.0244083 loss) I0304 23:01:14.809435 5094 sgd_solver.cpp:106] Iteration 5940, lr = 0.001 I0304 23:01:20.310364 5094 solver.cpp:228] Iteration 5960, loss = 0.0299701 I0304 23:01:20.310396 5094 solver.cpp:244] Train net output #0: loss = 0.0299701 (* 1 = 0.0299701 loss) I0304 23:01:20.310410 5094 sgd_solver.cpp:106] Iteration 5960, lr = 0.001 I0304 23:01:25.807876 5094 solver.cpp:228] Iteration 5980, loss = 0.00960639 I0304 23:01:25.807914 5094 solver.cpp:244] Train net output #0: loss = 0.00960641 (* 1 = 0.00960641 loss) I0304 23:01:25.807925 5094 sgd_solver.cpp:106] Iteration 5980, lr = 0.001 I0304 23:01:31.037081 5094 solver.cpp:337] Iteration 6000, Testing net (#0) I0304 23:01:52.026041 5094 solver.cpp:404] Test net output #0: accuracy = 0.31178 I0304 23:01:52.026075 5094 solver.cpp:404] Test net output #1: loss = 7.09174 (* 1 = 7.09174 loss) I0304 23:01:52.117260 5094 solver.cpp:228] Iteration 6000, loss = 0.00708895 I0304 23:01:52.117293 5094 solver.cpp:244] Train net output #0: loss = 0.00708897 (* 1 = 0.00708897 loss) I0304 23:01:52.117307 5094 sgd_solver.cpp:106] Iteration 6000, lr = 0.001 I0304 23:01:57.617044 5094 solver.cpp:228] Iteration 6020, loss = 0.0195226 I0304 23:01:57.617076 5094 solver.cpp:244] Train net output #0: loss = 0.0195226 (* 1 = 0.0195226 loss) I0304 23:01:57.617087 5094 sgd_solver.cpp:106] Iteration 6020, lr = 0.001 ^CI0304 23:01:58.722149 5094 solver.cpp:454] Snapshotting to binary proto file snapshot_iter_6025.caffemodel I0304 23:01:59.396268 5094 sgd_solver.cpp:273] Snapshotting solver state to binary proto file snapshot_iter_6025.solverstate I0304 23:01:59.598551 5094 solver.cpp:301] Optimization stopped early. I0304 23:01:59.598588 5094 caffe.cpp:222] Optimization Done.
6000回目のiterationの段階で、validationデータの正解率(Test net output #0: accuracy)が0.31178と低めで収束した。過学習している状態だと予想される。学習データが20枚しかないのが原因のように思われる。学習率を変えたり、Data Augumentationしたりと学習のノウハウが必要なところだろう
※参考
http://techblog.yahoo.co.jp/programming/caffe-intro/
http://qiita.com/CORDEA/items/9fad27ae024928b6a7b1
https://gist.github.com/rezoo/a1c8d1459b222fc5658f
【Caffe】ネットワークを可視化する
前回(【Caffe】特徴量抽出を行いSVMで物体識別する - いつもの作業の備忘録)使用したネットワークを可視化する
1.描画用Pydotインストール
以下の二つのコマンドを実行したが、apt-getはなくても動くかもしれない
$ sudo apt-get install python-pydot $ pip install pydot2
2.描画コマンド実行
以下のコマンドでネットワークを描画し、deploy.jpgで保存する
$ cd $CAFFE_HOME $ python/draw_net.py models/bvlc_reference_caffenet/deploy.prototxt deploy.jpg
可視化結果が下図
赤が畳み込み層、緑が活性化関数、オレンジがプーリング、青が正規化、グレーがデータらしい
もし、エラーが出る場合は以下のように対応
- AttributeError: 'module' object has no attribute 'bool_'
これは、import caffeした際に出るかもしれない。
$ cd $CAFFE_HOME/python $ aftfile="caffe_io" $ for file in `find . -name "*.py"`; do cat $file | sed -e "s/import [\w\.]*io/import $aftfile/g" | sed -e "s/caffe\.io/caffe\.$aftfile/g" > $file".tmp";mv $file".tmp" $file; done $ mv "caffe/io.py" "caffe/"$aftfile".py"
- Couldn't import dot_parser, loading of dot files will not be possible.
$ pip uninstall pyparsing $ pip install -Iv https://pypi.python.org/packages/source/p/pyparsing/pyparsing-1.5.7.tar.gz#md5=9be0fcdcc595199c646ab317c1d9a709 $ pip install pydot
※参考
http://www.installion.co.uk/ubuntu/precise/universe/p/python-pydot/install/index.html
http://stackoverflow.com/questions/15951748/pydot-and-graphviz-error-couldnt-import-dot-parser-loading-of-dot-files-will
https://groups.google.com/forum/#!topic/caffe-users/4r5dxoFpWxk
http://qiita.com/CORDEA/items/9fad27ae024928b6a7b1
http://wiki.ruka-f.net/index.php?Pydot