Yolo實作教學 — train出屬於自己的model使用darkflow (windows)

wayne shang
7 min readJan 13, 2019

--

前言

YOLO you only look once 今天要來介紹一下這個’開源技術來利用自己的資料庫訓練來偵測物件。

安裝Yolo

大家可以先到這個連結去下載repo(這裡面有蠻詳細的安裝簡介),因此這部分基本就不講了。

準備自己的訓練資料

  1. 首先需要很多的圖片data
    可以選擇從影片中去切割推薦使用free video to JPG這個現成的工具下載連結
  2. 再來需要對data進行整個過程中最枯燥乏味的Labeling工作
    可以使用下載連結選擇最新的下載就好(記得xml檔名字要跟圖片一樣且不要出現-符號或中文)
  3. 下載完後打開針對每張圖你想要的辨識的物件進行label的動作
  4. 在做label時要注意不要標到不相干的背景

在進行準備資料時可能很多人都會有疑問要準備多少張資料

就我自己的經驗而言這其實取決於你的資料複雜度
舉例來說:假如想辨識手這個物件,且你希望不論任何手的角度或姿勢都能準確預測的話,可能就需要每個角度每個姿勢各100張以上才有可能train到比較好的結果,但假如你選用的照片都太過類似(ex:背景都相同)很有可能造成overfitting,因此建議這部分大家可以自己先從至少300張照片嘗試。

開train前準備!!!

  1. 建立兩個資料夾一個放圖片另一個放label資料xml檔
    2. 創立一個label.txt裡面要有所有要分類的類別名稱
    3. 選擇適當cfg檔並修改其參數
    這裡可以先複製選擇的cfg 並重新命名成如下圖

注意假如要使用darkflow來執行不能使用yolov3的cfg
同時假如GPU內存比較小建議可以使用tiny-yolo類的cfg

4. 打開cfg檔後往下拉將class修改成你要辨識的類別數量,同時上面filter的部分要改成 5*(幾種類別+5)

5. 接下來就可以開始train了
在terminal 輸入以下的code:

python — model [model.cfg] —load [model.wieghts] — train — dataset [image path] — annotation [annotation path] — labels [labels path] — epoch [number of epoches] — gpu [0–1] — lr [learning rate] — batch [batch size]

epoch, lr(learning rate), batch size不設的話也沒關係會有default值
default值可以參考以下的圖片

假如想知道還有甚麼可以參數可自行設定可以去 dakflow/defaults.py 裡看

defaults.py參數

這邊介紹幾個小技巧:
1.假如要接著train 同一個model時, load 後面的weights只要改成 -1代表使用最後一次checkpoint記憶的參數繼續往下train
2. Learning rate 一開始可以設成0.001 epoch 設成 5, loss差不多就可以快速降到1左右, 之後再把learning rate調小就可以節省很多時間。
3. epoch 通常至少要train100個效果才會比較好

Testing

train完後就可以把圖片或影片拿進去model 看看結果了
以下是test data為圖片的code (threshold大小可以自行調整)

python flow --model cfg/yolo.cfg --load -1 --labels [labels path] --threshold 0.1 --imgdir sample_img/ --gpu [0~1]

以下為test data為影片的code
假如要用筆電webcam 將audiofile改成camera即可

python flow --model cfg/yolo.cfg --load -1 --labels [labels path] --demo [audiofile] --threshold 0.1 --saveVideo --gpu [0~1]

training 常見問題

我自己在train的時候遇到過蠻多問題

  1. 訓練完後testing data 餵進去完全沒有bounding box出現或是全部都是bounding box:
    這有可能是你的train data圖片太相似導致overfitting,
    或epoch跑太少單純需要讓機器再多跑多學習
    也可能是load 沒有改成-1所以抓不到你train好的物件
  2. train到一半loss變 nan
Training statistics: 
Learning rate : 1e-05
Batch size : 16
Epoch number : 1000
Backup every : 2000
step 1 - loss 9.513481140136719 - moving ave loss 9.51348114013672
step 2 - loss nan - moving ave loss nan
step 3 - loss nan - moving ave loss nan

這個原因應該是因為你的梯度爆炸

有幾個做法最簡單就是把learning rate 調小再試試看

不然就是要修改dakflow/net/flow.py 第56行修改成如下

gradients = optimizer.compute_gradients(self.framework.loss)
clipped_gradients = [(tf.clip_by_value(grad, -1., 1.), var) for grad, var in gradients]
self.train_op = optimizer.apply_gradients(gradients)

3. IndexError: list index out of range

出現這個問替表示你應該是有動到checkpoint 的檔案
這時候其實只要把原本輸入指令時 — load -1改成 — load [指定checkpoint的數字] 即可

4. 最後常見的問題OOM(out of memory)
就是你的記憶體爆了可以考慮把batch size調小只是會跑非常久

總結我自己的心得是data本身很重要,儘量不要出現很特例或不清楚的照片,然後有時候細選過的data train多點epoch會比很多datatrain很少epoch 效果好
最後祝大家都能順利做出來辨識自己想辨識的物件

--

--