caffeベースで配布されているネットワークをdockerで試す、Refinedetを題材に
caffe本家に含まれていない独自レイヤを使ったネットワークをcaffe実装で公開するとき、追加レイヤ分だけを含むリポジトリを作るのではなく、caffeごとforkして独自レイヤを足す形での配布が多いようです。
(というかそれしか手段がない?)
例えば、物体検出系で言うと、
あたりがそうですね。
これらをインストールしようとするとcaffeそのものをインストールされる以上、環境が汚れるのは必至、既存のcaffeとバージョンが衝突してどうしたものかなとなりますよね。
そんなときはdockerを使ってみようというお話。
dockerを使えばホスト環境を汚すことなく、コンテナ内でいろいろと試すことができます。
ただし、各ネットワークの配布元のDockerfileが保守されているとは限りません。
むしろfork後全く手付かずままのケースが多いです。
例えばSSDのDockerfileを見てみると
git clone -b ${CLONE_TAG} --depth 1 https://github.com/BVLC/caffe.git .
を実行する行が含まれています。
つまり、SSDのリポジトリではなく、本家のcaffeをクローンしてるので、dockerイメージをビルドしてもSSDは同梱されていません。(というかビルドすらできない可能性があります、闇。)
SSDはchainercvなどで試せばいいですが、Refinedetはまだ再現報告がなく、どうしても本家のRefinedetを試したかったので、RefinedetにはDockerfileを変更してRefinedetをビルドできるようにするPRいれてマージしてもらいました。
みなさんもdockerイメージで使いたいリポジトリがあったらPR入れてみてください。dockerの勉強にもなります。
docker版Refinedetの使い方
さて、せっかくPRを入れたので、docker版Refinedetの使い方をまとめてみます。
Refinedetについては前回の記事を読んでみてください。SSDよりも検出性能は高く、動作速度は匹敵するので、試す価値有りです。
イメージのビルド
まず、Refinedetリポジトリをクローンします。
$ git clone https://github.com/sfzhang15/RefineDet.git
$ cd ./docker
$ docker build -t refindet:cpu standalone/cpu
でビルドしてイメージをビルドできます。GPUを使いたい場合、
$ nvidia-docker build -t refindet:gpu standalone/gpu
でビルドしてください。nvidia-dockerおよび、CUDA8.0が動くドライバがインストールされていることが必要です。
パフォーマンスの関係上、CPUでRefindetをトレーニングするのはあまり現実的ではないです(一ヶ月以上かかる?」)。
intel caffeベースでRefinedetを再構築すれば速くなると思いますが、修羅の道。
というわけで、初心者はトレーニングにはGPUを使いましょう。
学習済ファイルを使って予測する分にはCPUでも問題なくできます。
ビルド確認
$ docker run -ti refinedet:cpu caffe --version
とコマンドを打って、
libdc1394 error: Failed to initialize libdc1394
caffe version 1.0.0-rc3
と表示されればOKです。
学習済重みファイルのダウンロード、デモの実行
デモの実行には学習済重みファイルとネットワークを定義するprototxtが必要になります。
つまり、'/opt/caffe/models/VGGNet/VOC0712/refinedet_vgg16_320x320/deploy.prototxt'
と'/opt/caffe/models/VGGNet/VOC0712/refinedet_vgg16_320x320/VOC0712_refinedet_vgg16_320x320_final.caffemodel'がコンテナ内に存在している必要があります。
ファイルはここからダウンロードして展開してください。そして展開後のファイルをdocker cpコマンドでコンテナにコピーします。
docker cpコマンドでコピーする前にコンテナの名前を獲得します。
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
1307fb0e9177 refinedet-cpu "/bin/bash" 18 seconds ago Exited (0) 15 seconds ago vibrant_engelbart
のような表示が現れます。この場合、vibrant_engelbartがコンテナ名なので、
$ docker cp ./deploy.prototxt vibrant_engelbart:/opt/caffe/:/opt/caffe/
としてやれば、ファイルをホストからコンテナの中にコピーすることができます。
ここから先は上の
$ docker start vibrant_engelbart
$ docker attach vibrant_engelbart
として、コンテナの中に入り、prototxtと重みファイルをそれぞれ'/opt/caffe/models/VGGNet/VOC0712/refinedet_vgg16_320x320/deploy.prototxt'
と'/opt/caffe/models/VGGNet/VOC0712/refinedet_vgg16_320x320/VOC0712_refinedet_vgg16_320x320_final.caffemodel'に移してください。そして
$ cd /opt/caffe
$ python ./test/refindet_demo.py --save_fig
を実行してください。CPUの場合、
$ python ./test/refindet_demo.py --save_fig --gpu_id -1
としてください。
正常に実行されていれば、結果はコンテナ内の/opt/caffe/examples/images内に*_dets.jpgという名前で格納されています。このファイルはホスト側で
$ docker cp vibrant_engelbart:/opt/caffe/examples/images/00456_dets.jpg .
とすることで取り出すことができます。
こちらはデモの結果の一つ。バスだけでなく、運転手まで検出できています。
Refinedetのトレーニング
docker内でRefinedetをトレーニングすることもできます。
トレーニングを開始する前に、プレトレーニング済重みファイルと、このページを参考に学習データをダウンロードすることが必要になります。コンテナからwgetするか、ホストでダウンロードして、docker cpコマンドでコンテナ内の/opt/caffe/models/VGGNet/VOC0712/に移してください(VOC2007、2012データを使う場合)。
あるいは、コンテナ起動時に
$ docker run -ti --volume=$HOME/data:/root/data refindet:gpu
とすることで、ホスト側のディレクトリをマウントすることもできます。
学習データから、LMDBの作成を行う必要がありますが、こちらはコンテナから行えます。
学習データは大きいので、ディスク容量がもったいないときはこちらがおすすめ。
コンテナ内にて、
$ cd /opt/caffe
$ bash ./data/VOC0712/create_list.sh
$ bash ./data/VOC0712/create_data.sh
で、LMDBを作成できます。ここまで、できれば、いよいよトレーニングを開始できます。
コンテナ内にて、
$ python examples/refinedet/VGG16_VOC2007_320.py
と打って、ロスの減少を確認します。
以上です。いろいろ書いてしまいましたが、コンテナのビルドは1コマンドでできるので、あとは必要なファイルを適切にダウンロードしておければ問題なくトレーニングを開始できます。
参考にしたページ
GitHub - sfzhang15/RefineDet: Single-Shot Refinement Neural Network for Object Detection