ChainerでYOLOv2をやってみる [訓練/学習編]

前回ChainerでYOLOv2をやったという記事にアクセスがまぁまぁあったので、
下書きのままだったYOLOv2の訓練/学習編を書いていきます。(メモ程度ですがご容赦ください)

YOLOv2の訓練手順(製作者様)↓
YOLOv2/YOLOv2_animal_train.md at master · leetenki/YOLOv2 · GitHub


[環境]
Ubuntu16.04
python3.5.2

windows7 64bitでも可能だと思います

[インストール]
以下のものを入れてない人は入れてください
pip3 install mock
pip3 install cupy


[画像収集]
・backup
・sample_images
・items
・backgrounds
以上の4つのフォルダを新規作成してください。

次に画像を収集します

python download_images.py

itemsフォルダ内に画像がダウンロードされたか確認します。


[画像生成]

python image_generate.py 

で画像がランダムに作られていきます。
ここでエラーが起こるので少し変更しました。
random_overlay_image関数の74,75行目の部分でエラーが起こります。

   y = int(np.random.randint(src_h-scale_item_h)) - int(shift_item_h)
   x = int(np.random.randint(src_w-scale_item_w)) -int( shift_item_w)

変更した関数ごとを載せます。

def random_overlay_image(src_image, overlay_image, minimum_crop):
    src_h, src_w = src_image.shape[:2]
    overlay_h, overlay_w = overlay_image.shape[:2]
    shift_item_h, shift_item_w = overlay_h * (1-minimum_crop), overlay_w * (1-minimum_crop)
    scale_item_h, scale_item_w = overlay_h * (minimum_crop*2-1), overlay_w * (minimum_crop*2-1)

    a = src_h-scale_item_h
    b = src_w-scale_item_w
    if a <= 1:
      a = 100
    if b <= 1:
      b = 100
    c = int(np.random.randint(a) - shift_item_h)
    d = int(np.random.randint(b) - shift_item_w)
    if c < 0:
      c = int(np.random.randint(a))
    if d < 0:
      d = int(np.random.randint(a))

    y = (int(c))
    x = (int(d))

    image = overlay(src_image, overlay_image, x, y)
    bbox = ((np.maximum(x, 0), np.maximum(y, 0)), (np.minimum(x+overlay_w, src_w-1), np.minimum(y+overlay_h, src_h-1)))

    return image, bbox

はい、汚いですすみません。とにかくrandintにマイナスを入れないようにすればいいと思います。
今回は恐竜のほかにカービーを混ぜました。それに伴い、パラサウロロフスさんは消去しました。
追加したカービー↓
f:id:weekendproject9:20171023144113p:plain
とてもかわいいですね。

もう一度image_generate.pyを実行して確認します。
f:id:weekendproject9:20171023143901p:plain


[darknet19(画像識別器)の訓練・テスト]
今回カービーを追加したのでdata/label.tetラベルを書き換えます。

Tyrannosaurus
Brachiosaurus
Triceratops
Riopururodon
Rhino
Dog
Erasmosaurus
Ammonite
kirby
Deer

*パラサウロロフスさんは消去しました。
*順番も順守
訓練

python darknet19_train.py

訓練終了後、テストします。

python darknet19_predict.py items/kirby.png

以下、結果です
f:id:weekendproject9:20171023154918p:plain

[darknet19_448の訓練・重み切り出し]
訓練する

python darknet19_448_train.py

backupフォルダにdarknet19_448_final.modelが保存されたか確認
つぎに重み切り出し

python partial_weights.py

backupフォルダにpartial.modelが保存されたか確認

[YOLOv2の訓練・テスト]

python yolov2_train.py

ここで私のPCではメモリ不足になってしまったので
88行目のloss.backward()の下に

loss.unchain_backward()

を追加します。
*これでメモリが解放されますが学習にどう響くかは不明です。。。
ちなみに3日~1週間の間、学習処理をしました。

無事、訓練が終わったらテストです。
しかし、テストするまえに
yolov2_predict.pyの12行目を変更を出力したモデルの名前に書き換えます

12    weight_file = "./backup/yolov2_final_cpu.model"
 ↓
12    weight_file = "./backup/yolov2_final.model"

認識テスト実行

python yolov2_predict.py test.jpg 

テスト画像↓
f:id:weekendproject9:20171023143910p:plain

結果
f:id:weekendproject9:20171023154934p:plain

以上、終わりです。




[参考]
Chainer2.0がリリース【今後の安定版】とりあえず抑えておきたい変更点 - HELLO CYBERNETICS
chainer-object-detection/model/yolov2 at master · dsanno/chainer-object-detection · GitHub