---
# System prepended metadata

title: Yolov3 訓練

---

# Yolov3 訓練
請先make 這個 darknet https://github.com/pjreddie/darknet

make教學可看(https://github.com/AlexeyAB/darknet)
Makefile裡面自行修改參數 
```
GPU=1
CUDNN=1
OPENCV=0 (若有安裝opencv [C++, 非opencv-python], 不能使用opencv 3.4.1)
OPENMP=1 (GNU Compiler Collection有支援)
DEBUG=0  (除錯用，一般用不到，別動)
```
arch提供參考參數如下(若為該架構就uncomment)
```
# 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]

# Tesla V100, GTX 1180, Titan V, Quadro GV100
# ARCH= -gencode arch=compute_70,code=[sm_70,compute_70]

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

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

# For Quadro GP100, Tesla P100
# ARCH= -gencode arch=compute_60,code=[sm_60,compute_60]

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

# For Quadro M6000 , GeForce 900, GTX-970, GTX-980, GTX Titan X :
# ARCH= -gencode arch=compute_52,code=[sm_52,compute_52]

# For Tesla/Quadro M series :
# ARCH= -gencode arch=compute_50,code=[sm_50,compute_50]

# For Tesla K80 :
# ARCH= -gencode arch=compute_37,code=[sm_37,compute_37]

# For Tesla K40 :
# ARCH= -gencode arch=compute_35,code=[sm_35,compute_35]

# For GeForce 700, GT-730 :
# ARCH= -gencode arch=compute_30,code=[sm_30,compute_30]

# For GeForce 400, 500, 600, GT-630 :
# ARCH= -gencode arch=compute_20,code=[sm_20,compute_30]
```
## 訓練資料為(假設是VOC格式)
DataSet的根目錄我用`path_to_dataset`代替.
首先準備voc dataset, 擺放方式如下:

```
path_to_dataset (dir)  
│
└───images (dir)
│   │
│   │   file001.jpg
│   │   file002.jpg
│   └   ...
│   
└───labels_voc (dir)
│   │   file001.xml
│   │   file002.xml
│   └   ...
│
└───labels (dir)
    │
    └─(empty) 


*註: (dir) 為資料夾
```
檔名請對齊，file001.jpg 就對應file001.xml

## Step1 VOC to darknet format
下載`label_to_yolo.py`至`path_to_dataset`根目錄:
https://gist.github.com/hsuRush/f6689a62a740f0cf3ffa3ff99a79b7df
`需改path_to_dataset跟class以及valid_split, valid_split`為train set, valid set切的比例. 若為0.1則比例為9:1.

- 跑`python label_to_yolo.py`他會將VOC label資料(在`path_to_dataset/labels_voc`)轉為darknet的格式並放入`path_to_dataset/labels/`，並且會產生train.txt以及test.txt

將產生train.txt以及test.txt放至`path_to_dataset/`


## Step2 Kmeans for anchor box
`kmeans.py`:
https://gist.github.com/hsuRush/4bf21fff72f00cb7e37c2af3f572a86e

預設`CLUSTERS` = 9

將`path_to_dataset`改為`labels_voc`所在的絕對路徑
將`HEIGHT`, `WIDTH`, `classes`改為你現在DataSet的規格
調整`times`, 他會多跑幾次然後選擇最好的kmeans結果.

好了之後跑`python kmeans.py` 他會輸出一個`k_means_anchor`

將`k_means_anchor`檔案以文本方式打開如下
```
Accuracy: 89.91%
anchors = 69,25,  78,33,  71,29,  44,19,  75,37,  47,23,  58,27,  91,42,  55,22 
```
將`darknet/cfg/yolov3.cfg` 複製出來, 假設叫yolov3_fruit.cfg
將`69,25,  78,33,  71,29,  44,19,  75,37,  47,23,  58,27,  91,42,  55,22`複製到yolov3_fruit.cfg裡面的`anchors = `. Take yolov3 as exmaple, change [Line 609](https://github.com/pjreddie/darknet/blob/0ff23438c66629deff8df2551baffbbb29987dee/cfg/yolov3.cfg#L609), [Line 695](https://github.com/pjreddie/darknet/blob/0ff23438c66629deff8df2551baffbbb29987dee/cfg/yolov3.cfg#L695), [Line 782](https://github.com/pjreddie/darknet/blob/0ff23438c66629deff8df2551baffbbb29987dee/cfg/yolov3.cfg#L782)
並且yolov3_fruit.cfg有兩處需要修改的地方：
第一處：[yolo]層中classes改成你的類別數(在v3中共三處)，假設我使用的是fruit的資料集，有3類，所以`classes=3`。
第二處：[yolo]層前一層的[convolution]層中(在v3中共三處)，filters的數量改成（`classes`+4+1 * `CLUSTERS`).
Take yolov3 as exmaple, change [Line 610](https://github.com/pjreddie/darknet/blob/0ff23438c66629deff8df2551baffbbb29987dee/cfg/yolov3.cfg#L603), [Line 696](https://github.com/pjreddie/darknet/blob/0ff23438c66629deff8df2551baffbbb29987dee/cfg/yolov3.cfg#L689), [Line 783](https://github.com/pjreddie/darknet/blob/0ff23438c66629deff8df2551baffbbb29987dee/cfg/yolov3.cfg#L776)
所以假設我kmeans跑得是(CLUSTERS=9)是(3+4+1)*9 = 72, 所以改為`filters=72`
Take yolov3 as exmaple, change [Line 609](https://github.com/pjreddie/darknet/blob/0ff23438c66629deff8df2551baffbbb29987dee/cfg/yolov3.cfg#L603), [Line 695](https://github.com/pjreddie/darknet/blob/0ff23438c66629deff8df2551baffbbb29987dee/cfg/yolov3.cfg#L689), [Line 782](https://github.com/pjreddie/darknet/blob/0ff23438c66629deff8df2551baffbbb29987dee/cfg/yolov3.cfg#L776)

## Step3 DataSet preparation
創.names 跟.data 
.names放class的名稱, 例如`darknet/data/fruit.names`的內容為
``` 
apple
banana
pineapple
```
例如 `darknet/cfg/fruit.data`內容為: 
```
classes= 3 (class個數)
train  = path_to_dataset/train.txt (train.txt的完整路徑) (產生於Step1)
valid =  path_to_dataset/test.txt (test.txt的完整路徑) (產生於Step1)
names = /home/username/darknet/data/fruit.names (fruit.names的完整路徑)
backup = /home/username/backup (訓練過程的暫存點checkpoint會存在這，要先創好資料夾先創好資料夾先創好資料夾)
```
# Step 4 Training Settings
![](https://i.imgur.com/DcnClFR.png)
將`yolov3_fruit.cfg`Testing部份如上圖所示`#`字號註解掉, Training無`#`字號。
將`yolov3_fruit.cfg`的max_batches,batch跟steps改成適當的數字 [參考](https://github.com/AlexeyAB/darknet#how-to-train-to-detect-your-custom-objects)

舉例我在cfg裡面設：
```
max_batches = 6000
policy=steps
steps=4000,5000
scales=.1,.1
```
在make成功darknet的情況下,
在darknet/ 打開terminal
* for `linux`:
  跑 `./darknet detector train cfg/fruit.data cfg/yolov3_fruit.cfg`

* for `window`:
  跑 `darknet.exe detector train cfg/fruit.data cfg/yolov3_fruit.cfg`
   
``-gpu 0,1,2...`` for multi-gpu

訓練的資訊請看 https://chtseng.wordpress.com/2018/09/01/%E5%BB%BA%E7%AB%8B%E8%87%AA%E5%B7%B1%E7%9A%84yolo%E8%BE%A8%E8%AD%98%E6%A8%A1%E5%9E%8B-%E4%BB%A5%E6%9F%91%E6%A9%98%E8%BE%A8%E8%AD%98%E7%82%BA%E4%BE%8B/ 的第八點

# Step 5 
訓練好後把cfg的testing 的`#`拿掉 training的部份加上`#`
![](https://i.imgur.com/DcnClFR.png)

若需要使用python inference, 請看
https://github.com/107368002/darknet/blob/48dcb887e8f8a7253e5dcdb4297b19b43b58ea55/python/darknet.py#L48

記得路徑要改 (48行)
```
lib=CDLL("/home/czchen/stevenwork/plate_detection_ML_hw3/darknet/libdarknet.so", RTLD_GLOBAL)
```
