Darknetで学習をするまでの手順

概要

今回は物体検出でよくお世話になるDarknetを用いてYolov4を学習するまでの手順を説明していきます。環境はUbuntuを想定しています。

おおまかな手順は以下の通り。

  • clone & ビルド
  • ファイル準備
  • 学習

Requirements for Windows, Linux and macOS

注意点としてはOpenCVです。pipでインストールしたやつではだめなので注意。

  • CMake >= 3.18
  • CUDA >= 10.2
  • OpenCV >= 2.4: use your preferred package manager (brew, apt), build from source using vcpkg or download from OpenCV official site (on Windows set system variable OpenCV_DIR = C:\opencv\build - where are the include and x64 folders image)
  • cuDNN >= 8.0.2
  • GPU with CC >= 3.0
  • 【windowsの場合】Powershell (already installed on windows): https://docs.microsoft.com/en-us/powershell/scripting/install/installing-powershell

clone & ビルド

clone

まずはcloneしてきましょう。

$ git clone https://github.com/AlexeyAB/darknet
$ cd darknet

ビルド

次にビルドを行います。 ビルドを行う前にMakefileを環境に合わせて書き換えます。 主に注目するところは2箇所。

1つ目はここ。使ってる環境に応じて変更します。

GPU=0
CUDNN=0
CUDNN_HALF=0
OPENCV=0
AVX=0
OPENMP=0
LIBSO=0
ZED_CAMERA=0
ZED_CAMERA_v2_8=0

# set GPU=1 and CUDNN=1 to speedup on GPU
# set CUDNN_HALF=1 to further speedup 3 x times (Mixed-precision on Tensor Cores) GPU: Volta, Xavier, Turing and higher
# set AVX=1 and OPENMP=1 to speedup on CPU (if error occurs then set AVX=0)
# set ZED_CAMERA=1 to enable ZED SDK 3.0 and above
# set ZED_CAMERA_v2_8=1 to enable ZED SDK 2.X
  • GPU環境を使っている場合はGPU,CUDNNを1に変更します。もしGPU環境がVolta, Xavier, Turing and higherであればCUDNN_HALFも1に変更します。
  • OPENCVは基本的に1に変更しておきます。学習曲線を描くのに使います。
  • CPU環境を使っている場合はAVX,OPENMPを1に変更することで高速化が可能になります。AVXが対応していないCPUだとエラーになるので、その時は0にしておきましょう。

2つ目はここ。

# GeForce RTX 3070, 3080, 3090
# ARCH= -gencode arch=compute_86,code=[sm_86,compute_86]

# Kepler GeForce GTX 770, GTX 760, GT 740
# ARCH= -gencode arch=compute_30,code=sm_30

# Tesla A100 (GA100), DGX-A100, RTX 3080
# ARCH= -gencode arch=compute_80,code=[sm_80,compute_80]

# Tesla V100
# ARCH= -gencode arch=compute_70,code=[sm_70,compute_70]

# GeForce RTX 2080 Ti, RTX 2080, RTX 2070, Quadro RTX 8000, Quadro RTX 6000, Quadro RTX 5000, Tesla T4, XNOR Tensor Cores
# ARCH= -gencode arch=compute_75,code=[sm_75,compute_75]

# Jetson XAVIER
# ARCH= -gencode arch=compute_72,code=[sm_72,compute_72]

# GTX 1080, GTX 1070, GTX 1060, GTX 1050, GTX 1030, Titan Xp, Tesla P40, Tesla P4
# ARCH= -gencode arch=compute_61,code=sm_61 -gencode arch=compute_61,code=compute_61

# GP100/Tesla P100 - DGX-1
# ARCH= -gencode arch=compute_60,code=sm_60

# For Jetson TX1, Tegra X1, DRIVE CX, DRIVE PX - uncomment:
# ARCH= -gencode arch=compute_53,code=[sm_53,compute_53]

# For Jetson Tx2 or Drive-PX2 uncomment:
# ARCH= -gencode arch=compute_62,code=[sm_62,compute_62]

# For Tesla GA10x cards, RTX 3090, RTX 3080, RTX 3070, RTX A6000, RTX A40 uncomment:
# ARCH= -gencode arch=compute_86,code=[sm_86,compute_86]

お使いのGPU環境に応じてARCH= の部分のコメントアウトを外してください。

上記2点を変更したらビルドをしましょう。

$ make

ビルドが成功したらdarknetというファイルができているはずです。

ファイル準備

続いてファイルの準備をします。ここでは 「画像は準備できていて、アノテーションは済んでいる」 という前提で話を進めていきます。また今回は犬猫の2クラスを検出するという設定でお話しします。最終的には以下のディレクトリ構成を目指します。それでは一つずつ見ていきます。

/data/
├── backup/
├── obj.data
├── obj.names
├── train/
│   ├── train_000.jpg
│   ├── train_000.txt
│   ├── train_001.jpg
│   ├── train_001.txt
│   └── ...
├── train.txt
├── valid/
│   ├── valid_000.jpg
│   ├── valid_000.txt
│   ├── valid_001.jpg
│   ├── valid_001.txt
│   └── ...
├── valid.txt
├── yolov4-custom.cfg
└── yolov4.conv.137

backup

学習された重みが保存されていくディレクトリです。作成しておきましょう。

obj.data

用意したファイルなどのパスを記述するファイルです。以下のような感じ。

classes = 2
train  = /data/train.txt
valid  = /data/valid.txt
names = /data/obj.names
backup = /data/backup/

obj.names

クラス名を記述するファイルです。上から順番にclass_idが振られるので、以下の例でいうとclass_id:0がDog, 1がCatとなります。

Dog
Cat

train/valid

train/validは画像とアノテーションデータを保存しておくディレクトリです。画像と同じディレクトリに同じ名前のテキストファイルを作ることで画像とアノテーションファイルをリンクさせます。

アノテーションファイルの例は以下の通り。

1 0.716797 0.395833 0.216406 0.147222
0 0.687109 0.379167 0.255469 0.158333
1 0.420312 0.395833 0.140625 0.166667

フォーマットは<object-class> <x_center> <y_center> <width> <height>のようにする。<x_center>,<y_center>,<width>,<height>に関しては画像サイズに対して割合で表現します。

  • <object-class>: class_idを記述
  • <x_center>: アノテーションの中心X座標 / 画像の横幅
  • <y_center>: アノテーションの中心Y座標 / 画像の縦幅
  • <width>: アノテーションボックスの横幅 / 画像の横幅
  • <height>: アノテーションボックスの縦幅 / 画像の縦幅

train.txt/valid.txt

学習に使う画像のパスを記述します。train.txtの場合は以下の通り。valid.txtも同様に記述します。

/data/train/train_000.jpg
/data/train/train_001.jpg
...

yolov4-custom.cfg

configファイルです。cloneしてきたものの中に/darknet/cfg/のディレクトリがあり、その中にyolov4-custom.cfgがあるのでそれをコピります。そしてその中身を書き換えます。

# Training
batch=64 #バッチサイズ
subdivisions=16 #バッチサイズをさらに小分け。この場合だと64/16で4となる。Out of memoryとなる場合は32,64と増やしていくとよい。
width=608 #入力横サイズ, 512,416とかにする場合がある
height=608 #入力縦サイズ, 512,416とかにする場合がある
max_batches = 6000 #クラス数*2000か最低6000が推奨とされている。今回の例では2クラスなので6000とする。
steps=4800,5400 #max_batches*0.8,max_batches*0.9で計算

最後に以下の部分。以下の記述はそれぞれ3つあるので全て書き換える。

[convolutional]
...
filters=21 #(class_num+5)*3で計算する, クラス数が2の場合は(2+5)*3=21となる

[yolo]
...
classes=2 #自分のクラス数に書き換える

yolov4.conv.137

学習済みモデルです、ダウンロードします。

$ wget https://github.com/AlexeyAB/darknet/releases/download/darknet_yolo_v3_optimal/yolov4.conv.137

学習

準備はこれで完了です!それでは学習をしていきます。

ビルドしたdarknetファイルがあるディレクトリに移動する。そこで以下のコマンドを打つ。これは一番基本的なものです。

./darknet detector train /data/obj.data /data/yolov4-custom.cfg /data/yolov4.conv.137

学習の際にはオプションをつけることが可能です。

  • -map: mapも学習曲線に描画する。
  • -dont_show: 学習曲線をGUI上でリアルタイム表示しないためのもの。サーバー上で学習をしていてGUI環境でない場合はこのオプションをつける。
  • -mjpeg_port 8090: GUI環境がないがリアルタイムで学習曲線を確認したい場合これをつける。ポートにアクセスすることで学習曲線が確認可能となる。

僕がよく使うのは上2つのオプションで、コマンドは以下となる。

./darknet detector train /data/obj.data /data/yolov4-custom.cfg /data/yolov4.conv.137 -map -dont_show

yolov4

最後に

Let’s enjoy training!

参考リンク