Yolov3でKITTIデータを学習してみる
前回はYolov3のAlexeyAB/Darknetをインストールしたので今回は学習してみる
環境
- Intel(R) Core(TM) i9-9900K CPU @ 3.60GHz
- 64GB RAM
- GeForce RTX 2080 Ti 11GB
- Ubuntu 18.04 LTS
学習データの準備
学習データとしてドイツのカールスルーエ工科大学とアメリカ・シカゴにある豊田工業大学シカゴ校のチームによる、自動車ビジョンのための画像データを使用する
- Download left color images of object data set (12 GB) (data_object_image_2.zip)
- Download training labels of object data set (5 MB) (data_object_label_2.zip)
上記からこの2つのファイルをダウンロードする。
これらを同じディレクトリで展開する
$ mkdir raw $ cd raw $ unzip data_object_image_2.zip $ data_object_label_2.zip $ ls training testing
学習画像はtraining/image_2
に、ラベルはtraining/label_2
にある
ラベルデータのフォーマットは
hirotaka-hachiya.hatenablog.com
このようになっているのでYolov3のラベルフォーマット
<ラベル> <矩形の中心座標x/画像幅> <矩形の中心座標y/画像高さ> <矩形の幅/画像幅> <矩形の高さ/画像高さ>
に変換する必要がある。
convert detectnet labeling format to yolov3 labeli ...
変換するスクリプトを書いた。
Pillow
を使ってるので適当にインストールしてください。
$ python detectnet2yolo.py [画像ディレクトリ] [ラベルディレクトリ]
と実行すると、カレントディレクトリにyolo_label
ディレクトリを作成してその中に変換したラベルデータとclasses.txt
を出力する
$ python detectnet2yolo.py training/image_2 training/label_2
Yoloでは画像とラベルは同一のディレクトリ内にある必要があるので
$ cd .. $ mkdir train_data $ cp raw/training/image_2/* data/ $ cp raw/yolo_label/* data/
このようにする。
次に、学習データとテストデータを振り分ける
generate yolo training and validation(test)
$ python generate_validation.py [データディレクトリ]
と実行すると、カレントディレクトリにtrain.txt
とtest.txt
を出力する
$ python generate_validation.py data/
darknetの設定
READMEを参照しながら設定していく
https://github.com/AlexeyAB/darknet/blob/master/cfg/yolov3.cfg
これを以下のように修正してcfg/yolo-obj.cfg
にコピーする
$ diff --git a/cfg/yolov3.cfg b/cfg/yolov3.cfg index 4a0ecc3..b01d980 100644 --- a/cfg/yolov3.cfg +++ b/cfg/yolov3.cfg @@ -1,10 +1,10 @@ [net] # Testing -batch=1 -subdivisions=1 +# batch=1 +# subdivisions=1 # Training -# batch=64 -# subdivisions=16 +batch=64 +subdivisions=16 width=416 height=416 channels=3 @@ -17,9 +17,9 @@ hue=.1 learning_rate=0.001 burn_in=1000 -max_batches = 500200 +max_batches = 18000 policy=steps -steps=400000,450000 +steps=14400,16200 scales=.1,.1 [convolutional] @@ -600,14 +600,14 @@ activation=leaky size=1 stride=1 pad=1 -filters=255 +filters=42 activation=linear [yolo] mask = 6,7,8 anchors = 10,13, 16,30, 33,23, 30,61, 62,45, 59,119, 116,90, 156,198, 373,326 -classes=80 +classes=9 num=9 jitter=.3 ignore_thresh = .7 @@ -686,14 +686,14 @@ activation=leaky size=1 stride=1 pad=1 -filters=255 +filters=42 activation=linear [yolo]下 mask = 3,4,5 anchors = 10,13, 16,30, 33,23, 30,61, 62,45, 59,119, 116,90, 156,198, 373,326 -classes=80 +classes=9 num=9 jitter=.3 ignore_thresh = .7 @@ -773,17 +773,18 @@ activation=leaky size=1 stride=1 pad=1 -filters=255 +filters=42 activation=linear [yolo] mask = 0,1,2 anchors = 10,13, 16,30, 33,23, 30,61, 62,45, 59,119, 116,90, 156,198, 373,326 -classes=80 +classes=9 num=9 jitter=.3 ignore_thresh = .7 truth_thresh = 1 random=1 +
batch=64 subdivisions=16
これについては
batch
がsubdivisions
で割り切れればいいよって情報と
subdivisions
が大きすぎると学習がうまく行かなくなったっていう情報があるのでよくわからない。
でもbatch
は64
のままで、
GPUのメモリと相談してsubdivisions
を8
,16
.32
と調整するのがいいみたい。
次にcfg/obj.data
を以下で作成する
classes = 9 train = train.txt valid = test.txt names = train_data/classes.txt backup = weights/
次に事前学習データをダウンロードする
$ wget https://pjreddie.com/media/files/darknet53.conv.74
次に学習結果を保存するディレクトリを作成する
$ mkdir weights
最後にラベルをリポジトリのdata/labels
からコピーしてくる
$ mkdir data $ cp -r (path to darknet)/data/labels data/
結果的にこのようなディレクトリ構成にする
$ tree . . ├── cfg │ ├── obj.data │ └── yolo-obj.cfg ├── darknet53.conv.74 ├── data │ └── labels │ ... ├── train_data │ ├── 000000.png │ ├── 000000.txt │ ├── 000001.png │ ├── 000001.txt │ ... ├── raw │ ├── training │ ... │ ├── testing │ ... │ └── yolo_label │ ... ├── test.txt ├── train.txt └── weights
学習する
$ darknet detector train cfg/obj.data cfg/yolo-obj.cfg darknet53.conv.74 -map
17時間後
detections_count = 11067, unique_truth_count = 5168 class_id = 0, name = Car, ap = 94.26% (TP = 2584, FP = 117) class_id = 1, name = Van, ap = 98.39% (TP = 312, FP = 21) class_id = 2, name = Truck, ap = 99.73% (TP = 103, FP = 2) class_id = 3, name = Pedestrian, ap = 72.65% (TP = 313, FP = 86) class_id = 4, name = Person_sitting, ap = 76.04% (TP = 21, FP = 4) class_id = 5, name = Cyclist, ap = 86.48% (TP = 138, FP = 18) class_id = 6, name = Tram, ap = 99.09% (TP = 65, FP = 4) class_id = 7, name = Misc, ap = 95.11% (TP = 105, FP = 7) class_id = 8, name = DontCare, ap = 36.97% (TP = 512, FP = 584) for conf_thresh = 0.25, precision = 0.83, recall = 0.80, F1-score = 0.82 for conf_thresh = 0.25, TP = 4153, FP = 843, FN = 1015, average IoU = 67.70 % IoU threshold = 50 %, used Area-Under-Curve for each unique Recall mean average precision (mAP@0.50) = 0.843033, or 84.30 % Total Detection Time: 8.000000 Seconds
mAPが84.3%なのでまぁまぁいい感じに学習できた
テストしてみる
raw/testing/image_2
にテスト用のデータがあるのでこれを入力してみる
$ darknet detector test cfg/obj.data cfg/yolo-obj.cfg weights/yolo-obj_best.weights raw/testing/image_2/000090.png ... raw/testing/image_2/000090.png: Predicted in 11.234000 milli-seconds. Car: 100% Car: 100% Car: 100% Car: 39% Car: 69% DontCare: 30%
ちゃんと学習できてる