YOLOをファインチューニングし、少量データセットで物体検知をカスタム
手持ちの少量のデータセットで、YOLO v3をファインチューニングし、カスタムした物体検知を行ないます。今回は、WHILL Model Cを画像から検知してみました。
YOLOv3で物体検知する方法を紹介しました。
Google Colab上でYOLO v3を使って、手持ちの画像の物体検知をしてみた
手持ちの少量のデータセットで、YOLOをファインチューニングし、カスタムした物体検知を行ないます。
今回は、WHILL Model Cを画像から検知してみました。
ファインチューニングは、学習済みのモデルの、ある畳み込みブロックの出力側の層を学習させ、入力側の層はパラメーターを凍結させます。
学習済みのモデルの表現の一部を新しい問題に適合させます。
ファインチューニングを使うことで、少量のデータセットでも性能を出せます。
以下のような概要で行ないました。
- iCrawlerを使って画像を集める
- LabelImgでアノテーションする
- darknet YOLOの設定ファイルをデータに合わせて修正する
- Google Colabで学習させる(ファインチューニング)
1.と2.は割愛します。
WHILL Model C全体が写っている画像を80枚用意しました。
GitHubからGoogle Colabに画像や設定ファイルを持っていくので、darknet YOLOを自分のGitHubにforkしておきます。
私がforkしたレポジトリは https://github.com/KazumichiShirai/darknet です。
forkができたら、2.で作った画像とアノテーションデータを/darknet/data/whillに置きます。
ディレクトリ名whillは任意の名前で大丈夫です。
まずローカル環境でdarknet/YOLOに変更を加えます。
変更後のコードはこちらに置きました。
https://github.com/KazumichiShirai/darknet
train.txtとtest.txtの用意
https://timebutt.github.io/static/how-to-train-yolov2-to-detect-custom-objects/
を参考にPythonスクリプトを書きました。
https://github.com/KazumichiShirai/darknet/blob/master/python/divide.py
使うときは、パスとopenするファイル名(whill-train.txt, whill-test.txt)を修正してください。
以下のコマンドを実行します。
python divide.py
訓練データセットはwhill-train.txtとして生成されます。
検証データセットはwhill-test.txtとして生成されます。
この2つのファイルは/darknet/cfgに置きます。
cfgファイルの作成
darknetではバッチ数やニューラルネット構造をcfgファイルで設定します。
yolov3.cfgをベースにcfgファイルを作成します。
学習に使うwhill-frozen.cfgと検出で使うwhill.cfgを作成します。
yolov3.cfgをコピーして、whill-frozen.cfgを作成します。
yolov3.cfgから次のような変更をしました。
batchとsubdivisionsを変更。
batch=16
subdivisions=4
max_batchを変更。
max_batchの回数だけ学習を繰り返すので、max_batchが大きいと学習がなかなか終わりません。
max_batchは(検出したいcleassの数) x 2000 が目安のようです* 。
分類したい物体はWHILL Model Cの1つなので、2000となります。
多めに学習を繰り返すために、4000としました。
max_batches = 4000
stepsはmax_batchesの80%,90%に設定します。
steps=3200,3600
分類したい数classesとfilterを変更します。
分類したい物体は1つなので、classes=1とします。
filterは(classes + 5)*mask数で計算します。
yolov3.cfgではmask=6,7,8のようにmaskは3種類になっています。
よって、filter=18に変更します。
classesとfilterはそれぞれ3箇所書かれているので、すべて変更します。
classes=1
filters=18
今回はファインチューニングで学習しました。
darknet YOLOではstopbackward=1を使って、凍結させる層を設定できます。
こちら
のように、548行目に
stopbackward=1
を追加しました。
学習を終えた重みを使って検出を実行するときには、検出用のcfgファイルが必要です。
検出用のcfgファイルでは、batchとsubdivisionsを1とします。
検出用のcfgファイルをwhill.cfgとして、whill-frozen.cfgから次のような変更をしました。
Testingの直後に書かれいてるbatch, subdivisionsのコメントアウトを外して、Training直後に書かれているbatch, subdivisionsをコメントアウトします。
[net]
# Testing
batch=1
subdivisions=1
# Training
# batch=16
# subdivisions=4
2つのcfgファイル(whill-frozen.cfg, whill.cfg)はdarknet/cfgに置きます。
namesファイルの作成
namesファイルには分類したいクラス名を入れます。
今回はWHILL Model Cのみなので、WHILLModelCと1行だけ書きます。
ファイル名はwhill.namesにして、darknet/dataに置きました。
WHILLModelC
dataファイルの作成
分類したいクラスの数と作成したファイルへのパスをdataファイルに記載します。
classes= 1
train = cfg/whill-train.txt
valid = cfg/whill-test.txt
names = data/whill.names
backup = backup
今回はWHILL Model Cのみ検出したいので、classes=1となります。
backupに指定したパスには、学習途中と学習完了時の重みが保存されます。
GPU利用有効化のためのmakefile修正
YOLOのGPU利用を有効化するために、makefileを修正します。
GPU=1
ローカル環境での作業は以上です。
変更をコミットして、Google Colabでの作業に移ります。
ここからGoogle Colabでの作業になります。
Google ColabのハードウェアアクセラレータはGPUに変更しておきましょう。
参考:Google Colab上でYOLO v3を使って、手持ちの画像の物体検知をしてみた
実行したコードはこちらにコピーしました。
whill_model_c_yolo.ipynb
ビルドと学習済み重みのダウンロード
forkしたdarknet/YOLOを、GitHubからcloneしてビルドします。
%%bash
git clone https://github.com/KazumichiShirai/darknet
cd darknet
make
ImageNetで学習済みの重みをダウンロードします。
!wget https://pjreddie.com/media/files/darknet53.conv.74
ファイルを保存するために、Google Driveをmountしておきます。
from google.colab import drive
drive.mount('/content/gdrive')
ファインチューニング
ダウンロードした重みからファインチューニングします。
出力されるログはlogファイルにリダイレクトさせています。
%%bash
cd ./darknet/
./darknet detector \
train \
cfg/whill.data \
cfg/whill-frozen.cfg \
/content/darknet53.conv.74 > /content/log
これで学習が終わるまで待ちます。
学習が終わるまで、4~5時間程度かかりました。
学習が終わると、backupディレクトリにwhill-frozen_final.weightsという重みが保存されています。
どの時点での重みがよさそうか、また充分な性能が出ていそうか、logファイル見ながら検証する必要がありますが、ここでは割愛します。
backupディレクトリにある重みは、Google Colabのインスタンスが落ちると消えてしまうので、すぐにGoogle Driveに保存しましょう。
%cp /content/darknet/backup/whill-* /content/gdrive/My\ Drive/tmp/
学習後の重みでテストしてみる
学習には使わなかった画像を使って、WHILL Model Cが検出できるかテストしてみます。
Google Driveに、学習には使わなかったsample.JPGを置いて、確認します。
%%bash
cd ./darknet
./darknet detector test cfg/whill.data cfg/whill.cfg /content/gdrive/My\ Drive/tmp/whill-frozen_final.weights /content/gdrive/My\ Drive/tmp/sample.JPG
結果はpredictions.jpgとして出力されます。
predictions.jpgを表示させます。
from IPython.display import Image,display_jpeg
display_jpeg(Image('darknet/predictions.jpg'))
WHILL Model Cの検知ができました!
参考にさせていただいたサイト
Yolo-v3 and Yolo-v2 for Windows and Linux How to train YOLOv2 to detect custom objects Google Colab上でdarknet(YOLO)を使って物体を数える【画像認識】 YOLOオリジナルデータの学習
Share this post
Twitter
Facebook
LinkedIn