にせねこメモ

はてなダイアリーがUTF-8じゃないので移ってきました。

WindowsでChainerCVのサンプルを動かしFaster R-CNNをトレーニングしてみる

先日のChainer Meetupにて、ChainerCVというライブラリを知った。

Chainerの上で動作する、コンピュータビジョンタスクのためのディープラーニングライブラリとのことである。

このChainerCVで、Faster R-CNNによる物体検出が簡単に利用できるらしく、exampleを動かすことで試してみた。

環境

記事時点でのChainer, ChainerCVのバージョンは以下の通り。

  • Chainer: 2.0.0
  • ChainerCV: 0.5.1

ディープラーニングWindows使うとつまらない所でひっかかって割とつらいのでLinux使うべきだと思う。

インストー

  1. Chainer (Version 2.0.0)とCuPyをインストールする。
  2. 必要なライブラリが入ってなければpipで入れる
    • 必須: Cython, Pillow
    • 任意: Matplotlib, OpenCV
  3. 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

とすると、検出結果が表示される🐱
f:id:nixeneko:20170623002835p:plain

train.py

これはモデルのトレーニング用プログラムで、次のようにして実行する。0番目のGPUを使用する設定にしている*1

python train.py --gpu 0

しかし、Windowsでは実行すると次のようなエラーが発生する。

AttributeError: Can't pickle local object 'main.<locals>.transform'

このサイトによると、multiprocessingがサブプロセスを生成する方法がUnixWindowsで異なっていることがエラーの原因らしい。

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

すると、先ほどと同様の結果が出力された。
f:id:nixeneko:20170624093754p:plain

*1:GTX 1060で10時間ほど、CPUだと60日程度かかるらしい。