先日のChainer Meetupにて、ChainerCVというライブラリを知った。
Chainerの上で動作する、コンピュータビジョンタスクのためのディープラーニングライブラリとのことである。
このChainerCVで、Faster R-CNNによる物体検出が簡単に利用できるらしく、exampleを動かすことで試してみた。
環境
記事時点でのChainer, ChainerCVのバージョンは以下の通り。
- Chainer: 2.0.0
- ChainerCV: 0.5.1
インストール
- Chainer (Version 2.0.0)とCuPyをインストールする。
- 必要なライブラリが入ってなければpipで入れる
- 必須: Cython, Pillow
- 任意: Matplotlib, OpenCV
- ChainerCV (Version 0.5.1)をインストールする
- Anacondaプロンプトを開き、次を実行する:
pip install chainercv
これでインストールは完了。
あと、(v0.5.1の) examplesを動かしてる時に、データをダウンロードするところでZeroDivisionErrorで止まったので、
chainercv/utils/download.py (C:\Anaconda3\Lib\site-packages\chainercv\utils\download.py などにある)の25行目
speed = int(progress_size / (1024 * duration))
がdurationが0での時でも動くように書き換える:
try: speed = int(progress_size / (1024 * duration)) except ZeroDivisionError: speed = float('inf')
これは最新のリポジトリでは直ってるので、新しいバージョンがリリースされれば解決される問題であると思う。
examplesを動かしてみる
ソースコードをとってくる
git clone https://github.com/chainer/chainercv.git cd chainercv git checkout v0.5.1 cd examples/faster_rcnn
demo.py
demo.pyは物体検出を行い、結果を表示する。デフォルトでは、トレーニング済みのモデルをネットからダウンロードしてきてそれを利用する。
適当な画像hoge.jpgを用意して
python demo.py hoge.jpg
とすると、検出結果が表示される🐱
train.py
これはモデルのトレーニング用プログラムで、次のようにして実行する。0番目のGPUを使用する設定にしている*1。
python train.py --gpu 0
しかし、Windowsでは実行すると次のようなエラーが発生する。
AttributeError: Can't pickle local object 'main.<locals>.transform'
このサイトによると、multiprocessingがサブプロセスを生成する方法がUnixとWindowsで異なっていることがエラーの原因らしい。
Unixではデフォルトでforkによりサブプロセスを作るが、Windowsではforkは使えず、spawnによってサブプロセスを生成する。
このspawnでサブプロセスを生成する際、targetはpickableである(pickleでシリアライズできる)必要があるとのこと。特に、関数内に定義された関数はpickableでないので、モジュールのトップレベルに持ってくる必要がある。
エラーメッセージを見ると、train.pyのmain関数内に定義されたtransform関数が引っかかっているようである。なので、transform関数をトップレベルまで持ってくれば良さそうだ。
train.pyのfaster_rcnnの定義とtransform関数の定義をmain関数の定義の前に持ってくると、とりあえず動くようになった。faster_rcnnはtransformの中で参照されているため、これもトップレベルにもってくる。
faster_rcnn = FasterRCNNVGG16(n_fg_class=len(voc_detection_label_names), pretrained_model='imagenet') def transform(in_data): img, bbox, label = in_data _, H, W = img.shape img = faster_rcnn.prepare(img) _, o_H, o_W = img.shape scale = o_H / H bbox = transforms.resize_bbox(bbox, (H, W), (o_H, o_W)) # horizontally flip img, params = transforms.random_flip( img, x_random=True, return_param=True) bbox = transforms.flip_bbox( bbox, (o_H, o_W), x_flip=params['x_flip']) return img, bbox, label, scale def main(): #(略)
この様に変更した後に、
python train.py --gpu 0
を実行し、トレーニングループを回し、終了するまで待つ。
トレーニングが終わると、デフォルトではresult/snapshot_model.npzにトレーニング後のモデルが保存される。
なので、それを指定してdemo.pyを実行する:
python demo.py --pretrained_model "result/snapshot_model.npz" hoge.jpg
すると、先ほどと同様の結果が出力された。
*1:GTX 1060で10時間ほど、CPUだと60日程度かかるらしい。