【目標(biāo)檢測實戰(zhàn)】Darknet—yolov3模型訓(xùn)練(VOC數(shù)據(jù)集)

19.jpg

0.前言

本文為Darknet框架下魁巩,利用官方VOC數(shù)據(jù)集的yolov3模型訓(xùn)練牺汤,訓(xùn)練環(huán)境為: Ubuntu18.04下的GPU訓(xùn)練,cuda版本10.0妓盲;cudnn版本7.6.5杂拨。經(jīng)過一晚上的訓(xùn)練,模型20個類別的mAP達(dá)到74%+悯衬。

主要模塊:

  • 概述
  • 源碼編譯
  • 功能測試
  • 模型訓(xùn)練
  • 模型驗證

【概述】部分主要介紹yolo系列模型和darknet框架的關(guān)系扳躬、資源網(wǎng)站和數(shù)據(jù)集下載
【源碼編譯】主要是用官方源碼和make命令編譯出Linux下可執(zhí)行文件,包括cuda+cudnn的設(shè)置
【功能測試】主要是用官網(wǎng)給出的demo和與訓(xùn)練模型來進(jìn)行圖片測試
【模型訓(xùn)練】主要是用darknet+yolov3模型訓(xùn)練VOC圖像數(shù)據(jù)集(VOC2007+VOC2012)
【模型驗證】即用訓(xùn)練好的模型甚亭,檢測模型訓(xùn)練效果.

1.概述

官網(wǎng):https://pjreddie.com/

1.1 Yolo

Yolo系列模型(v1~v3)在近年些來的目標(biāo)檢測領(lǐng)域贷币,非常火熱亏狰!Yolo為:You only look once的縮寫役纹,同時也表明了其特點,只需要一次即可完成從圖像分割到檢測暇唾,故其被稱為one-stage系列模型的鼻祖促脉。

two-stage類目標(biāo)檢測模型如Fast R-CNN、Faster R-CNN

屏幕截圖_1.png

1.2 Darknet

yolo系列就是深度學(xué)習(xí)領(lǐng)域中用于目標(biāo)檢測的模型(yolov1~v3)策州,那么darknet是什么瘸味?兩者關(guān)系如何?
darknet是作者用c和cuda編寫的用于深度學(xué)習(xí)模型訓(xùn)練的框架够挂,支持CPU和GPU訓(xùn)練旁仿,是個非常簡單輕量級框架,就和Tensorflow,Mxnet孽糖,Pytorch,Caffe一樣枯冈,雖然功能沒有它們多毅贮,不過小也有小的優(yōu)勢,如果你會c語言尘奏,可以對其進(jìn)行充分地利用和改造滩褥,或者讀讀源碼看一下其實現(xiàn),也會收貨滿滿炫加!
So,總結(jié)一下:Darknet是深度學(xué)習(xí)框架瑰煎,yolov1~v3是yolo系列的目標(biāo)檢測模型

1.3 資源下載

官網(wǎng)

https://pjreddie.com/

源碼

Darknet源碼:
https://github.com/pjreddie/darknet

Darknet是用純c和cuda編寫的,要想用darknet來訓(xùn)練模型俗孝,最好用Linux/Unix系統(tǒng)丢间,官方也提供了python的接口,如果是Windows系統(tǒng)驹针,可以利用網(wǎng)友開源實現(xiàn):https://github.com/AlexeyAB/darknet

可以直接下載zip包??darknet-master.zip也可直接執(zhí)行
git clonehttps://github.com/pjreddie/darknet將源碼下載到本地

權(quán)重文件

yolov3-tiny.weights
yolov2.weights
yolov3.weights
darknet53.conv.74

VOC數(shù)據(jù)集

VOCtrainval_11-May-2012.tar
VOCtrainval_06-Nov-2007.tar
VOCtest_06-Nov-2007.tar

其他:

YOLO-V3可視化訓(xùn)練過程中的參數(shù)烘挫,繪制loss、IOU柬甥、avg Recall等的曲線圖:https://blog.csdn.net/qq_34806812/article/details/81459982
AlexyAB大神總結(jié)的優(yōu)化經(jīng)驗:
https://www.cnblogs.com/pprp/p/10204480.html

2.源碼編譯

2.1 編輯Makefile

指定是否使用GPU

在執(zhí)行make指令編譯之前饮六,需要編輯一下makefile,來指定是否需要用GPU(cuda)苛蒲,如果用cuda卤橄,是否需要用cudnn加速;是否需要用opencv等臂外。我這里是用GPU且需要用CUDNN加速的窟扑,不使用OpenCV。

Makefile的前5行如下漏健,這5項內(nèi)容0表示不啟用嚎货,1表示啟用,可根據(jù)需求自己配置殖属。

  • GPU 是否啟用GPU1
  • CUDNN 是否啟用CUDNN加速瓦盛,若GPU = 1則CUDNN可選1或0;GPU=0則CUDNN=0
  • OPENCV 是否啟用OpenCV,啟用的話需先編譯安裝好原环,啟用可支持對視頻和圖像流文件處理
  • OPENMP 是否啟動多核CPU來加速Yolo,如果是用CPU訓(xùn)練挠唆,建議開啟=1
  • DEBUG 表示編譯的Yolo版本為是否為DEBUG版

屏幕截圖_14.png

如果不使用GPU則GPU=0,CUDNN=0玄组;還有一點需注意,如果在shell執(zhí)行nvcc找不到命令(沒有添加到環(huán)境變量),則需要將nvcc命令的全路徑寫出來

指定cuda的路徑

如果不使用GPU,則此步可忽略巧勤,如果使用GPU,則需要指定cuda路徑弄匕。官方的Makefile默認(rèn)的cuda路徑為:/usr/local/cuda,如果你裝了多個cuda剩瓶,但是有軟連接指向正確的cuda文件夾路徑:即/usr/local/cuda軟連接到你需要的cuda文件夾延曙,那么無需修改亡哄,保持/usr/local/cuda即可;否則需要指定你的cuda路徑愿卸,這里需要改兩處:51行的COMMON和53行的LDFAGS趴荸。

屏幕截圖_15.png

2.2 執(zhí)行make

屏幕截圖_16.png

執(zhí)行make編譯完成后发钝,在項目主目錄下生成可執(zhí)行的darknet文件波闹。然后我們就可以用這個可執(zhí)行文件來進(jìn)行模型訓(xùn)練和測試了精堕!

3.功能測試

將下載好的權(quán)重文件放入主目錄下,然后cd到該目錄下執(zhí)行:

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

如果你看到如下輸出夺英,且在主目錄下找到一張predictions.jpg的圖片滋捶,則執(zhí)行成功重窟,表明上一步驟中編譯的darknet可以正常使用。

屏幕截圖_17.png

你也可以指定一個閾值扭仁,yolo默認(rèn)輸出置信度>0.25的預(yù)測框乖坠,你也可以自行指定:

./darknet detect cfg/yolov3.cfg yolov3.weights data/dog.jpg -thresh 0.45

-thresh 0.45表示:置信度低于45%的預(yù)測框都不會被輸出熊泵。

除了使用經(jīng)典的yolov3模型外,你還可以換一個模型嘗試徐许,譬如yolov3-tiny.weights

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

當(dāng)然雌隅,也可以通過連接攝像頭實現(xiàn)實時視頻畫面預(yù)測缸沃。(需要編譯時添加opencv)

./darknet detector demo cfg/coco.data cfg/yolov3.cfg yolov3.weights <video file>

4.模型訓(xùn)練

4.1 數(shù)據(jù)準(zhǔn)備

模型訓(xùn)練前首先準(zhǔn)備數(shù)據(jù)集和泌,我們用VOC數(shù)據(jù)集,將VOC數(shù)據(jù)集解壓梯皿,解壓后共同存放在VOCevkit文件夾中东羹,我將VOCevkit放在了darknet主文件夾/data/VOC/下忠烛。

cd到/VOC目錄下美尸,下載??voc_label.py 师坎,并運行:

python voc_label.py

可以將該腳本復(fù)制到/scripts下留作備份

文件夾下會生成7個.txt文件:

屏幕截圖_17.png

如果你的voc_label.py腳本是從官網(wǎng)wget https://pjreddie.com/media/files/voc_label.py下載的胯陋,則需要在腳本57行處額外加上如下兩行內(nèi)容:

os.system("cat 2007_train.txt 2007_val.txt 2012_train.txt 2012_val.txt > train.txt") os.system("cat 2007_train.txt 2007_val.txt 2007_test.txt 2012_train.txt 2012_val.txt > train.all.txt")

目的:將2007年的訓(xùn)練和驗證圖像+2012年的圖像都放入了train.txt用于集中訓(xùn)練

4.2 修改配置文件voc.data

配置cfg/voc.data,來確定你需要檢測的目標(biāo)類別數(shù)量和名稱;修改train和valid的圖片資源路徑义矛。訓(xùn)練資源指向train.txt測試/驗證資源指向2007_test.txt

屏幕截圖_23.png

VOC數(shù)據(jù)集默認(rèn)的類別數(shù)量為20個凉翻,名稱在data/voc.names中:

屏幕截圖_19.png

我這里使用默認(rèn)的20個類別噪矛,所以無需修改艇挨;如果韭赘,你只想檢測其中的幾個類別泉瞻,譬如person和car袖牙,那么可以設(shè)置voc.data中classes=2,names只保留person和car這兩種,不過后面相應(yīng)的需要更改yolov3-voc.cfg里的卷積層配置等司忱。

4.3 修改yolov3-voc.cfg

yolov3-voc.cfg文件定義了yolo的卷積神經(jīng)網(wǎng)絡(luò)模型畴蹭,和超參數(shù)配置等叨襟。這里需要注意糊闽,訓(xùn)練時需要將#Testing區(qū)塊下的batch和subvisions注釋掉;測試和驗證時則放開注釋汽纠,同時注釋掉#Training區(qū)塊下的內(nèi)容虱朵。

訓(xùn)練時,可以根據(jù)自己GPU的內(nèi)存來設(shè)置批的大小batch絮宁,可設(shè)為16绍昂、32偿荷、64跳纳、128
驗證時,batch和subvisions同時設(shè)為1即可艾蓝。

屏幕截圖_22.png

4.4 開始訓(xùn)練

cd回項目主目錄赢织,將darknet53.conv.74權(quán)重放入主目錄下于置,運行:

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

如果報錯提示cuda內(nèi)存溢出八毯,可以降低batch曹步,再次運行讲婚;運行過程中可以通過nvidia-smi查看顯存占用情況:

屏幕截圖_24.png

訓(xùn)練過程中會持續(xù)往backup/下生成權(quán)重文件筹麸,如:yolov3-voc_100.weights、yolov3-voc_200.weights....

5.模型驗證

檢驗生成的模型權(quán)重文件白指、測試準(zhǔn)確率和map等指標(biāo)告嘲。驗證前需要將yolov3-voc.cfg中的batch和subdivisions都改成1橄唬。然后找到需要測試的權(quán)重文件,默認(rèn)權(quán)重文件保存在:項目目錄/bakcup/下隆判,我選擇這個yolov3-voc_10000.weights僧界,訓(xùn)練大約一個晚上12小時左右捂襟,loss在0.6多笆豁。

屏幕截圖.png

5.1 測試

測試一

我們從VOC數(shù)據(jù)集中隨便找一找圖片來測試一下闯狱,這里我選取000275.jpg放入主目錄下

000275.jpg

運行:

./darknet detector test cfg/voc.data cfg/yolov3-voc.cfg backup/yolov3-voc_10000.weights 000275.jpg

屏幕截圖_1.png

運行結(jié)束會在控制臺打印出標(biāo)注出的目標(biāo)類別以及置信度哄孤、同時會在目錄下生成一張標(biāo)注圖片:predictions.jpg

predictions.jpg

測試二

再隨便找一張圖片試試

>./darknet detector test cfg/voc.data cfg/yolov3-voc.cfg backup/yolov3-voc_10000.weights data/person.jpg

屏幕截圖_2.png
predictions.jpg

5.2 驗證

測試只能一張張地直觀感受下模型的訓(xùn)練效果,看看標(biāo)注出的目標(biāo)是否正確晨逝,通過驗證才能確定模型的整體訓(xùn)練效果捉貌,驗證時會用模型對所有的4952張測試集圖片進(jìn)行預(yù)測冬念,同時與正確結(jié)果進(jìn)行比對急前,得出一個模型預(yù)測準(zhǔn)確率。

驗證測試集

可以運行以下腳本進(jìn)行驗證:

./darknet detector valid cfg/voc.data cfg/yolov3-voc.cfg backup/yolov3-voc_10000.weights
驗證完會在results文件夾下生成20個類別的驗證結(jié)果txt文件

屏幕截圖_3.png

默認(rèn)的文件命名規(guī)則是:'comp4_det_test_' + '類別名稱' + .txt寺晌,如bird類生成comp4_det_test_bird.txt文件折剃。

屏幕截圖_4.png

如圖怕犁,第一列000053表示圖像編號己莺;第二列為置信度凌受;后4列為檢測出的目標(biāo)框坐標(biāo)

計算map

計算map,我們需要兩個python文件:

  • voc_eval.py
  • compute_mAP.py

其中voc_eval.py是github上開源項目的代碼voc_eval.py;compute_mAP.py需要我們自己編寫


voc_eval.py
我們?yōu)榱诉m配darknet中voc數(shù)據(jù)集的驗證挠进,需要對源碼做幾處修改:
a.源碼第9行:import cPickle 改為:

import _pickle as cPickle

因為源碼是python2.x版本领突,如果python3.x版本的運行會報錯君旦,故需要修改嘲碱。

b.源碼103行: imagenames ``=`` [x.strip() ``for`` x ``in`` lines]改為:

imagenames = [x.strip().split('/')[-1].split('.')[0] for x in lines]

這個主要是為了方便適配2007_test.txt麦锯,因為我們驗證時采用的是2007_test.txt中的測試集圖片扶欣,文件中存放的是圖片的全路徑,而imagenames需要用的是文件名昆著、所以需要將全路徑做個轉(zhuǎn)換凑懂,截取到文件名梧宫。

c.115行:with`` ``open``(cachefile, ``'w'``) ``as`` f:和 119行with`` ``open``(cachefile, ``'r'``) ``as f:改成:

with open(cachefile, 'wb') as f:
with open(cachefile, 'rb') as f:

如果不修改成‘wb’和‘rb’存儲二進(jìn)制格式,運行時會報錯

compute_mAP.py
新建compute_mAP.py文件巷帝,用于調(diào)用voc_eval.py,內(nèi)容如下:

from voc_eval import voc_eval
import os
map_ = 0
# classnames填寫訓(xùn)練模型時定義的類別名稱
classnames = ['aeroplane','bicycle','bird','boat','bottle','bus','car','cat','chair','cow','diningtable','dog','horse','motorbike','person','pottedplant','sheep','sofa','train','tvmonitor']
for classname in classnames:
    ap = voc_eval('../results/{}.txt', '../data/VOC/VOCdevkit/VOC2007/Annotations/{}.xml', '../data/VOC/2007_test.txt', classname, '.')
    map_ += ap
    #print ('%-20s' % (classname + '_ap:')+'%s' % ap)
    print ('%s' % (classname + '_ap:')+'%s' % ap)
# 刪除臨時的dump文件
if(os.path.exists("annots.pkl")):
    os.remove("annots.pkl")
    print("cache file:annots.pkl has been removed!")
# 打印map
map = map_/len(classnames)
#print ('%-20s' % 'map:' + '%s' % map)
print ('map:%s' % map)

我這里在項目主目錄下新建了一個【yolo-compute-util】文件夾楞泼,將兩個.py文件放在文件夾中堕阔,cd /yolo-compute-util颗味,然后運行:python compute_mAP.py即可根據(jù)results中的驗證結(jié)果統(tǒng)計出各個類別的ap,以及匯總的map浦马。

屏幕截圖_5.png

可以看見晶默,經(jīng)過1晚上的訓(xùn)練荤胁,我們的模型——yolov3-voc_10000.weights的mAP是0.740屎债,雖然沒有達(dá)到y(tǒng)olov2系列76.8+的水平盆驹,不過一晚上的訓(xùn)練能達(dá)到如此程度,也是挺高了辫封。

屏幕截圖_6.png
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市欣福,隨后出現(xiàn)的幾起案子焦履,更是在濱河造成了極大的恐慌,老刑警劉巖栖博,帶你破解...
    沈念sama閱讀 217,657評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件仇让,死亡現(xiàn)場離奇詭異躺翻,居然都是意外死亡获枝,警方通過查閱死者的電腦和手機省店,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評論 3 394
  • 文/潘曉璐 我一進(jìn)店門懦傍,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人说榆,你說我怎么就攤上這事签财∑” “怎么了灸叼?”我有些...
    開封第一講書人閱讀 164,057評論 0 354
  • 文/不壞的土叔 我叫張陵古今,是天一觀的道長捉腥。 經(jīng)常有香客問我,道長披诗,這世上最難降的妖魔是什么呈队? 我笑而不...
    開封第一講書人閱讀 58,509評論 1 293
  • 正文 為了忘掉前任宪摧,我火速辦了婚禮几于,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘朽砰。我一直安慰自己瞧柔,他們只是感情好睦裳,可當(dāng)我...
    茶點故事閱讀 67,562評論 6 392
  • 文/花漫 我一把揭開白布哥蔚。 她就那樣靜靜地躺著蛛蒙,像睡著了一般宇驾。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上课舍,一...
    開封第一講書人閱讀 51,443評論 1 302
  • 那天,我揣著相機與錄音办桨,去河邊找鬼。 笑死损姜,一個胖子當(dāng)著我的面吹牛摧阅,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播顾孽,決...
    沈念sama閱讀 40,251評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼蜒什!你這毒婦竟也來了灾常?” 一聲冷哼從身側(cè)響起爽锥,我...
    開封第一講書人閱讀 39,129評論 0 276
  • 序言:老撾萬榮一對情侶失蹤仔戈,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后晋修,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體墓卦,經(jīng)...
    沈念sama閱讀 45,561評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡落剪,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,779評論 3 335
  • 正文 我和宋清朗相戀三年忠怖,在試婚紗的時候發(fā)現(xiàn)自己被綠了凡泣。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片鞋拟。...
    茶點故事閱讀 39,902評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖贺纲,靈堂內(nèi)的尸體忽然破棺而出航闺,到底是詐尸還是另有隱情,我是刑警寧澤哮笆,帶...
    沈念sama閱讀 35,621評論 5 345
  • 正文 年R本政府宣布来颤,位于F島的核電站,受9級特大地震影響稠肘,放射性物質(zhì)發(fā)生泄漏福铅。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,220評論 3 328
  • 文/蒙蒙 一项阴、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧环揽,春花似錦略荡、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,838評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至通今,卻和暖如春粥谬,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背辫塌。 一陣腳步聲響...
    開封第一講書人閱讀 32,971評論 1 269
  • 我被黑心中介騙來泰國打工漏策, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人臼氨。 一個月前我還...
    沈念sama閱讀 48,025評論 2 370
  • 正文 我出身青樓掺喻,卻偏偏與公主長得像,于是被迫代替她去往敵國和親储矩。 傳聞我的和親對象是個殘疾皇子感耙,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,843評論 2 354

推薦閱讀更多精彩內(nèi)容