標記工具
labelimg:下載後是壓縮檔,直接解壓縮即可。
將所有圖片存入資料夾內<D:\darknetYolo\test\images>,按Open Dir鈕,選擇要標記的圖片的資料夾<D:\darknetYolo\test\images>,再按 Change Save Dir鈕,選擇存放標記文字檔的資料夾(<D:\darknetYolo\test\labels>),PascalVOC鈕可以切換不同儲存格式,我們使用Yolo格式,按Create RectBox鈕即可開始標記。
此次標記有四種,「height」、「chest」、「waist」、「ass」,按Create RectBox後可開始標記,使用滑鼠框選出要標記的物件後放開,在labelimg對話方塊中輸入標籤名稱後再按Save即可。
結束後將images內的圖片複製至labels內,使他們能夠對應。
建立訓練組態資料結構
要讓Yolo訓練的資料有固定的安排方式,darknet才能找到資料進行訓練。因此要撰寫程式進行組態資料結構自動化。
Yolov3訓練模型主要有yolov3和yolov3-tiny兩種模式,對應的組態檔為<yolov3.cfg>及<yolov3-tiny.cfg>,皆位於<D:\darknetYolo\darknet\cfg>資料夾中。yolov3模式的神經網路遠比yolov3-tiny模式多,因此模型準確度較高,但訓練的時間也比yolov3-tiny長。
複製<D:\darknetYolo\darknet\cfg>資料夾內的<yolov3.cfg>及<yolov3-tiny.cfg>檔,將須修正的部分以特殊字串代替,並另存新檔放至<test>資料夾內,命名為<yolov3-obj.cfg>、<yolov3-tiny-obj.cfg>,程式執行時會將這兩個檔案複製到指定位置,並依訓練資料進行修改。
<yolov3-obj.cfg>檔修正的部分為:
1 [net]
2 # Testing
3 batch=[[batch]]
4 subdivisions=[[subdivisions]]
......
602 pad=1
603 filters=[[filters]]
......
610 classes=[[classes]]
......
688 pad=1
689 filters=[[filters]]
......
696 classes=[[classes]]
......
775 pad=1
776 filters=[[filters]]
......
783 classes=[[classes]]
第3列 batch設定每批次處理多少筆資料,第4列subdivisions定每批次資料分為幾次處理,即每次處理batch/subdivisions筆資料,此數值越大訓練速度越快,但耗費的記憶體越多。若訓練發生記憶體不足,可以將subdivisions加大或將batch減少。
610、696、783列的classes值為標記名稱的數量,例如前面身體部位有四類標記名稱,則classes=4。603、689、776列的filters數值為(classes+5)x3,例如身體範例的filters=(4+5)x3=27。
<yolove-tiny-obj.cfg>檔修正的部分再3、4、127、135、171、177列,修正的方式與<yolov3-obj.cfg>相同。
<makecfg.py>可自動建立整個訓練組態資料結構
打開spyder,並將路徑設為<D:\darknetYolo\test>
def emptydir(dirname): #清空資料夾
if os.path.isdir(dirname): #資料夾存在就刪除
shutil.rmtree(dirname)
sleep(2) #需延遲,否則會出錯
os.mkdir(dirname) #建立資料夾
import glob
import os, shutil
import wget
from time import sleep
import random
batch = 24 #設定每批次處理的資料數量。
subdivisions = 2 #設定每批次資料分幾次處理。
classname = ['height','chest','waist','ass'] #分類標籤
train = 'cfg/train.txt' #建立訓練資料檔路徑
valid = 'cfg/valid.txt' #建立驗證資料檔路徑
names = 'cfg/obj.names' #分類標籤名稱檔
backup = 'cfg/weights' #儲存訓練模型資料夾
validratio = 0.1 #設定驗證資料佔全部資料數量的比例
print('開始建立設定資料!')
#下載預訓練檔
if not os.path.exists("darknet53.conv.74"): #若預訓練檔不存在就下載
wget.download('https://pjreddie.com/media/files/darknet53.conv.74') #下載檔案
emptydir('cfg') #建立<cfg>資料夾存放訓練組態資料結構
emptydir(backup) #在<cfg>資料夾中建立<weights>資料夾存放訓練後的權重檔。
#建立<obj.data>,darknet系統利用此檔內容讀取訓練組態資料結構進行訓練
classes = len(classname) #分類標籤數量
f = open('cfg/obj.data', 'w')
out = 'classes = ' + str(classes) + '\n'
out += 'train = ' + train + '\n'
out += 'valid = ' + valid + '\n'
out += 'names = ' + names + '\n'
out += 'backup = ' + backup + '\n'
f.write(out)
#建立標籤檔
f = open(names, 'w') #建立<cfg/obj.names>檔
out =''
for cla in classname:
out += cla + '\n'
f.write(out)
#建立訓練及驗證資料檔
imgfiles = glob.glob('labels/*.jpg') #讀取圖形檔
for i in range(len(imgfiles)):
imgfiles[i] = imgfiles[i].replace('\\', '/')
validnum = int(len(imgfiles) * validratio) #根據驗證資料比例變數值計算驗證資料數量。
validlist = random.sample(imgfiles, validnum) #取出驗證資料
f = open(valid, 'w')
out =''
for val in validlist:
out += val + '\n'
f.write(out)
f = open(train, 'w')
out =''
for tra in imgfiles:
if tra not in validlist: #不是驗證資料就是訓練資料
out += tra + '\n'
f.write(out)
#建立組態檔
cfglist = ['yolov3-tiny-obj.cfg', 'yolov3-obj.cfg'] #將兩個組態檔按名稱建立陣列以便能用迴圈處理
for cfgfile in cfglist:
shutil.copyfile(cfgfile, 'cfg\\' + cfgfile) #複製檔案
f = open('cfg\\' + cfgfile, 'r') #讀取檔案內容
content = f.read()
#替換資料
content = content.replace('[[batch]]', str(batch))
content = content.replace('[[subdivisions]]', str(subdivisions))
content = content.replace('[[classes]]', str(classes))
content = content.replace('[[filters]]', str((classes+5)*3))
f = open('cfg\\' + cfgfile, 'w')
f.write(content)
f.close()
print('建立設定資料完成!')
訓練模型
使用本機
訓練模型的語法為
darknet.exe 路徑 detector train obj.data檔路徑 組態檔路徑 darknet53.conv.74
在<D:\darknetYolo\test>搜尋列輸入cmd,並執行以下命令即可開始訓練
..\darknet\darknet.exe detector train cfg\obj.data cfg\yolov3-tiny-obj.cfg darknet53.conv.74
如果電腦出現「記憶體不足」的錯誤,以文字編輯器開啟<yolov3-tiny-obj.cfg>,將第四列subdivisions的值改為8,若仍錯誤,則依序修改為16、32、64進行訓練。
如果電腦因各種因素導致訓練過程中斷,或覺得訓練次數不夠,效果不理想,可以至<D:\darknetYolo\test\cfg\weights>將自動產生的<yolov3-tiny-obj_last.weights>權重檔取代<darknet53.conv.74>檔即可,系統就會由前次訓練中斷處繼續訓練:
..\darknet\darknet.exe detector train cfg\obj.data cfg\yolov3-tiny-obj.cfg cfg\weights\yolov3-tiny-obj_last.weights
如果想要訓練Yolov3模型,命令為:
..\darknet\darknet.exe detector train cfg\obj.data cfg\yolov3-obj.cfg darknet53.conv.74
使用Colab
開啟Colab,登入後點選新增記事本,並至編輯→筆記本設定,將硬體加速器改為GPU,並點選右上角的連線。
將<D:\darknetYolo\test>資料夾複製一份,並命名為<test_colab>。要上傳到Colab的只有<labels>資料夾、<cfg>資料夾、<darknet53.conv.74>檔案,其他刪除,並將<test_colab>資料夾壓縮為<test_colab.zip>檔,再將<test_colab.zip>檔上傳到Google Drive雲端硬碟<Colab Notebooks>資料夾中。
即可上Colab進行程式撰寫。
首先,先將筆記本存取你的 Google 雲端硬碟檔案,如下圖依序操作。
複製darknet系統原始碼:
!git clone https://github.com/AlexeyAB/darknet.git
darknet組態設定檔是<Makefile>,使用「cat」命令查看其設定:先切換到<darknet>資料夾,然後顯示<Makefile>內容
%cd darknet
!cat Makefile -n
會看到GPU、CUDNN、OpenCV都預設未使用(0),必須將他們都設為1,使用「sed」命令將0取代為1
!sed -i "s/GPU=0/GPU=1/g" Makefile
!sed -i "s/CUDNN=0/CUDNN=1/g" Makefile
!sed -i "s/OPENCV=0/OPENCV=1/g" Makefile
!cat Makefile -n
進行編譯
!make
接著切回根目錄,複製<test_colab.zip>壓縮檔到根目錄並解壓縮。
%cd /content
!ln -s "/content/drive/My Drive/Colab Notebooks" /godrive
!cp /godrive/test_colab.zip /content
!unzip test_colab.zip
%cd /content/test_colab #進入解壓縮之資料夾內
機器學習訓練通常需要相當長時間,因此在記憶體能承受的範圍內盡量提高批次處理資料量,藉以提高訓練速度
可先查看<yolov3-obj.cfg>檔案內容:
!cat cfg/yolov3-obj.cfg -n
subdivisions的值是4,沒問題!但若是<yolov3-tiny-obj.cfg>的值會是16,就可將其值改為8再進行訓練,用以下語法
!sed -i "s/subdivisions=16/subdivisions=8/g" cfg/yolov3-tiny-obj.cfg
開始訓練
!/content/darknet/darknet detector train cfg/obj.data cfg/yolov3-obj.cfg darknet53.conv.74 -dont_show
如果要用Yolov3-tiny-obj.cfg模型,只需將前面訓練Yolov3模型中的「Yolov3-obj.cfg」改成「Yolov3-tiny-obj.cfg」即可。
下載訓練權重檔
訓練模型時,每訓練1000次會自動產生一個權重檔,權重檔存於<content\cfg\weights>資料夾內
由於Colab一旦離線後,儲存在虛擬機器的資料會全部不見,萬一發生問題,將無法取得虛擬機器中的權重檔,因此最好每隔一段時間就下載權重檔到本機儲存。
使用既有權重檔繼續訓練
假設我們將訓練10000次的權重檔<yolov3-obj_10000.weights>下載到本機後,Colab發生問題離線,可以先將<yolov3-obj_10000.weights>上傳到Google Drive雲端硬碟的<Colab Notebooks>資料夾,執行下列命令。
!ln -s "/content/drive/My Drive/Colab Notebooks" /godrive
!cp "/godrive/Colab Notebooks/yolov3-obj_10000.weights" /content
!/content/darknet/darknet detector train cfg/obj.data cfg/yolov3-obj.cfg yolov3-obj_10000.weights -dont_show