darknet yolov3導入のイロハ

f:id:Ryotaro_Kubo:20181226232631p:plain

 

 まず、darknetという名前から厨二病っぽい感じがプンプンである。

 

とはいえ、yolov3は素晴らしく使いやすい。

 

https://pjreddie.com/darknet/yolo/

 

上記のサイトがyolov3のオフィシャルサイトになるわけだが、

如何せん自前データのトレーニングの手順は不親切な書き方をしている。

 

なので、わかりやすくまとめ直そうと思う。

 

Windowsでdarknetのyolov3を使うことに成功した(Ubuntuでは失敗)

ここにも簡単な手順も書いたが、

今回はWindowsじゃない人向けに、わかりやすくかく。

 

といっても、手順は割と明確である。

 

コマンドで以下をじゃんじゃん実行してもらえばオッケーだ。

 

git clone https://github.com/pjreddie/darknet

cd darknet

これでdarknetのファイル自体は出来上がった。

 

ここでGPU環境の整っている人はdarknet直下にあるmakefileを開いて

GPU=0

GPU=1

に変更する。

 

GPU環境のない人はそのままでオッケー!

 

ちなみに、

 

OpenCV=0

 

 についてだが、

これはリアルタイム(デモ)でdarknetを使いたい人には、

必須となる。

 

リアルタイム予測って何?

という人は後からでもmakeし直せるので

とりあえずはいじらなくて良い。

 

ただし、

リアルタイム予測で使いたい人は

OpenCV の環境を整えた上で、

 

OpenCV=0

OpenCV=1

 

に変更する必要がある。

 

ここまでできたら、

 

make

 

を走らせてコンパイルが完了した。

 

 これで本体が完成したので、

次にウェイトをダウンロードする。

 

wget https://pjreddie.com/media/files/yolov3.weights

 

実はもうこれで画像判定のサンプルデータと学習済みのウェイトが入った。

 

では、早速サンプルデータでテストを回してみよう。

 

./darknet detect cfg/yolov3.cfg yolov3.weights data/dog.jpg

 

これを打ち込むと

f:id:Ryotaro_Kubo:20181225233136p:plain

この有名な画像がdarknetフォルダ直下にできる。

 

実はもうこれで、darknetはあなたのものだ。

 

ここまでは楽だったが、

いざ自分のデータを学習させるとなると、

 

とーっても不親切なのだ。

 

VOCでのトレインの方法

 

まずは必要なものをコマンドでインストールしましょう。

 

wget https://pjreddie.com/media/files/VOCtrainval_11-May-2012.tar
wget https://pjreddie.com/media/files/VOCtrainval_06-Nov-2007.tar
wget https://pjreddie.com/media/files/VOCtest_06-Nov-2007.tar
tar xf VOCtrainval_11-May-2012.tar
tar xf VOCtrainval_06-Nov-2007.tar
tar xf VOCtest_06-Nov-2007.tar

 

これでVOCdevkitというフォルダに

アノテーション済みの大量のデータが入る。

 

データ量が割と半端ないので時間かかるかもだけどちょいそこは辛抱。

 

次に、以下を走らせる。

 

wget https://pjreddie.com/media/files/voc_label.py
python voc_label.py

 

これでdarknetを動かすpythonスクリプトが入った。

pythonは入っている前提で話しています。

 

そしたら、

散り散りになっていたアノテーションデータのラベルをまとめる。

 

cat 2007_train.txt 2007_val.txt 2012_*.txt > train.txt

 

これで必要なテキストデータをtrain.txtにまとめた。

 

後は、学習のモデルをダウンロードする。

 

wget https://pjreddie.com/media/files/darknet53.conv.74

 

これで全て必要なものはダウンロードが完了した。

 

「ん?これのどこがしんどいの?」

と言いたくなる気持ちはわかります。ご心配なく。

 

実は一番面倒なのはこれから。

 

順を追って書いていこう。

 

自分の用意した画像を学習させるには、

いくつか変更しなければならない点がある。

 

変えなければいけないことは

①/darknet/cfg/voc.data

②/darknet/data/voc.names

③/darknet/cfg/yolov3.cfg

④/darknet/train.txt

の4つ。

 

1つずつ変える内容を見ていこう。

 

①/darknet/data/voc.names

 

このファイルを開くと、

デフォルトの状態は

 

aeroplane

bicycle

bird

boat

bottle

bus

sofa

train

tvmonitor

 

と20個の英単語が並んでいる。

 

この単語1つ1つは、

 

class(クラス)

 

と呼ばれるものである。

この後も出てくるから覚えておいてほしい。

 

変更する点はクラスの中身だ。

 

デフォルトのクラスを消して、

自分が判定してほしい画像のクラス名を入れる。

 

例えば、

サッカーボールや野球ボールなどのボールの違いを認識させたいならば

 

soccerball

baseball

tennisball

volleyball

という感じで書けばオッケー。

 

そして、このクラスの数が

後に出てくるvoc.dataのclassesに該当する数になる。

 

②/darknet/cfg/voc.data

 

このファイルは開くと、

 

classes=20 
train = train.txt
valid = test.txt
names = data/data.names
backup = backup

 

と書いてあるのだが、

 

・classes=20

のところは①で出てきたvoc.namesに記載したクラスの合計数に20を変更する。

 

・train=train.txt

のところは /darknet/train.txt が存在するパスを書く。

 

パス自体は絶対でも相対でも大丈夫だが、

自分は絶対パスを書いていた。

 

 

・valid=test.txt

のところもtrain.txtと全く同じで

/darknet/test.txt が存在するパスを書く。

 

・namesとbackupは上の書き方から変更しなくても大丈夫。

 

よって具体的な例を出すと、こんな感じになる

 

classes=15
train = home/user/darknet/train.txt
valid = home/user/darknet/test.txt
names = data/data.names
backup = backup

 

③yolov3.cfg

 

こーいつが最もややこしい。

まず開くと

# Testing
# batch=1
# subdivisions=1
# Training
batch=64
subdivisions=16
width=608
height=608
channels=3
momentum=0.9
decay=0.0005
angle=0
saturation = 1.5
exposure = 1.5
hue=.1

 

こんな塊があると思う。

自前データを学習させるためには 

 上から5行目の初めて#が消える行

batch=64

batch=32

に変える。

 

これは変えなくても学習できるのだが、

変えたほうが、学習が回りやすくなる。

 

時折#の場所が変なとこについてるので上の通りにすると良い。

 

次に「コマンド+F」を利用してyoloという文字列を見つける。

これが3箇所あるはず。

 

[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
num=9
jitter=.3
ignore_thresh = .7
truth_thresh = 1
random=1

こんな感じの塊。

ここの中のうちの、

 

classes=80

 

を先ほど②で変更した

classes=

における変更後の数字に書き換える。

 

[yolo]の塊それぞれにclasses書き換えポイントは存在するので、

3つ全て書き換える必要がある。

 

さらに検索したそれぞれの[yolo]の一つ上にある、

[convolutional]の中のfiltersの数字を

 

(classesの数字+5)*3

 

に書き換える。

 

具体的に、

例えばclasses=15だとすると、

 

[convolutional]
size=1
stride=1
pad=1
filters=255
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
num=9
jitter=.3
ignore_thresh = .7
truth_thresh = 1
random=1

と書いてあるところを

 

[convolutional]
size=1
stride=1
pad=1
filters=60
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=15
num=9
jitter=.3
ignore_thresh = .7
truth_thresh = 1
random=1

に書き換える。(この60は(15+5)*3=60によって算出されたもの)

 

[yolo]が合計3箇所あるのでそれぞれについて訂正してあげて、

結局計6箇所修正をすれば良い。

 

これで完了。。。

 

④train.txt

 

これは簡単。

 

学習させるときに、

どこに学習用の画像とテキストファイルが入ってるかわからないと、

学習のしようがない。

 

なので、

train.txtに学習させたい画像のパスを全て追加する。

 

例えば学習させたいデータが

 

home/user/darknet/data/soccball_img1.jpg

home/user/darknet/data/soccball_img2.jpg

home/user/darknet/data/soccball_img3.jpg

home/user/darknet/data/soccball_img4.jpg

 

とかだったら、

素直にこのパスを全てtrain.txtに書けば良い。

 

自前の学習を回すときは、

train.txtの中身を全て削除してから

空のテキストファイルに学習させたいデータのパスを入れる。

 

あと気をつけなければならない点は、

学習させたい画像データと同じ名前のtxtファイルを

画像データと同じディレクトリに入れておくことだ。

 

これがないと学習できない。

 

txtファイルはlabelImgなどがアノテーションしやすくていい。

もちろんスクリプト書いて自動生成するのもあり。

 

 わかりやすくさっきの例をそのまま使うと

 

home/user/darknet/data/soccball_img1.jpg

home/user/darknet/data/soccball_img2.jpg

home/user/darknet/data/soccball_img3.jpg

home/user/darknet/data/soccball_img4.jpg

 これらの画像を学習させたければ、

 

home/user/darknet/data/soccball_img1.txt

home/user/darknet/data/soccball_img2.txt

home/user/darknet/data/soccball_img3.txt

home/user/darknet/data/soccball_img4.txt

も用意しましょうということだ。

 

txtファイルの中身は

 

<クラスNo.> <領域の中心のx座標> <領域の中心のy座標> <領域の幅> <領域の高さ>

 

となって入ればオーケーだ。(この中身の作り方もlabelImgを使えば手軽にできる)

 

ここまで全て変更を完了したらもう後は学習を回すだけ!

 

./darknet detector train cfg/voc.data cfg/yolov3.cfg darknet53.conv.74 

 

このコマンドを走らせれば後はもうだーっと学習が進むだけ。

 

学習のアヴェレージが1.5くらいまで下がったら

もう学習はある程度完了しているので最後まで学習させ切らずとも、

 

画像認識はできるようになっている。

 

ここまでの手間を書いていないのだから、

不親切!と思ってしまうだろう。

 

ただし

使えるようになると非常に便利なので、

 

ぜひ粘って使ってあげてください、、