目錄
一、安裝darknet
$ git clone https://github.com/pjreddie/darknet
$ cd darknet
二、編譯(這裏直接安裝cpu版本作爲例子)
make
GPU版本參考官網 https://pjreddie.com/darknet/install/;關於CUDA安裝參考https://mp.csdn.net/postedit/84945540
編譯成功後執行:
$ ./darknet
輸入如下即爲安裝成功:
三、製作數據集
1、進入 darknet-master/scripts 目錄裏創建類似VOC數據集下的這幾個文件夾
主要使用 Annotations、ImageSets裏的Main 和 JPEGImages 這三個文件夾
2、文件配置介紹
1)Annotations文件夾裏存放xml標籤文件:
)
2)ImageSets裏的Main文件夾裏存放訓練集和驗證集:
這兩個文件裏面的內容只需填要圖片的名稱即可,不需要後綴名
比如我的圖片是:00001.jpg,那麼我只要寫00001即可
traint.txt格式如下:(text.txt一樣的格式)
3)JPEGImages文件夾裏存放訓練集和驗證集的圖片文件
全部圖片放在一起即可,到時程序會根據你的train.txt和test.txt去找你的圖片和對應的標籤文件,所以要保證同一張圖片對應的標籤文件的名稱一樣
3、利用scripts目錄下的voc_label.py腳本生成到時候訓練時調用的圖片關聯txt文件
這裏的voc_label.py要修改兩個地方
##sets那個地方改成剛剛在Main裏面添加了那個文件的名稱
##Classes那個地方列表裏的內容改成你自己數據的類的名稱
以及註釋掉最後那兩行
整個文件是這樣子的
import xml.etree.ElementTree as ET
import pickle
import os
from os import listdir, getcwd
from os.path import join
sets=[('2007', 'train'), ('2007', 'test')]
classes = ["P", "G"]
def convert(size, box):
dw = 1./(size[0])
dh = 1./(size[1])
x = (box[0] + box[1])/2.0 - 1
y = (box[2] + box[3])/2.0 - 1
w = box[1] - box[0]
h = box[3] - box[2]
x = x*dw
w = w*dw
y = y*dh
h = h*dh
return (x,y,w,h)
def convert_annotation(year, image_id):
in_file = open('VOCdevkit/VOC%s/Annotations/%s.xml'%(year, image_id))
out_file = open('VOCdevkit/VOC%s/labels/%s.txt'%(year, image_id), 'w')
tree=ET.parse(in_file)
root = tree.getroot()
size = root.find('size')
w = int(size.find('width').text)
h = int(size.find('height').text)
for obj in root.iter('object'):
difficult = obj.find('difficult').text
cls = obj.find('name').text
if cls not in classes or int(difficult)==1:
continue
cls_id = classes.index(cls)
xmlbox = obj.find('bndbox')
b = (float(xmlbox.find('xmin').text), float(xmlbox.find('xmax').text), float(xmlbox.find('ymin').text), float(xmlbox.find('ymax').text))
bb = convert((w,h), b)
out_file.write(str(cls_id) + " " + " ".join([str(a) for a in bb]) + '\n')
wd = getcwd()
for year, image_set in sets:
if not os.path.exists('VOCdevkit/VOC%s/labels/'%(year)):
os.makedirs('VOCdevkit/VOC%s/labels/'%(year))
image_ids = open('VOCdevkit/VOC%s/ImageSets/Main/%s.txt'%(year, image_set)).read().strip().split()
list_file = open('%s_%s.txt'%(year, image_set), 'w')
for image_id in image_ids:
list_file.write('%s/VOCdevkit/VOC%s/JPEGImages/%s.jpg\n'%(wd, year, image_id))
convert_annotation(year, image_id)
list_file.close()
#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")
然後執行voc_label.py
$ python voc_label.py
這時會生成2個東西,這兩個東西后面要用到的
第一個,在 darknet-master/scripts/VOCdevkit/VOC2007 目錄下得到labels文件夾,這時我們的VOC2007已經存在四個文件夾了
我們打開其中一個label裏面的文件看看
##前面第一個數字0代表的就是前面我們在classes列表裏定義的第一個標籤類—P
##後面的4個數字就是之前在xml文件裏的ground truth框框的xmin xmax ymin ymax的座標啦,這裏自動將座標除以圖像的寬和高進行歸一化了
第二個,在 darknet-master/scripts 目錄下,會得到 2007_train.txt 和 2007_test.txt 這兩個文件:
我們打開2007_train.txt文件看看,這裏面是訓練集圖片的具體路徑位置,它將會作爲後期訓練的一個索引文件來找到那些數據集
到這裏數據集就準備好了
四、修改訓練配置文件
1、修改訓練初始化超參數(我們這裏以yolov3-tiny爲例子)
/darknet-master/cfg 目錄下有很多版本的cfg網絡文件,我們打開yolov3-tiny.cfg進行超參數設置
下面我對每個參數做了註釋,其實要更改的地方是 ##注意## 所在行的參數
[net]
# Testing ### 測試模式
#batch=1
#subdivisions=1
# Training ### 訓練模式,每次前向的圖片數目 = batch/subdivisions
batch=64 ###這個地方改成64。 ##注意##這裏 batch=64
subdivisions=2 ##注意##這裏 subdivisions=2
width=720 ### 網絡的輸入寬、高、通道數
height=1280
channels=3
momentum=0.9 ### 動量
decay=0.0005 ### 權重衰減
angle=0
saturation = 1.5 ### 飽和度
exposure = 1.5 ### 曝光度
hue=.1 ### 色調
learning_rate=0.001 ### 學習率
burn_in=1000 ### 學習率控制的參數
max_batches = 10000 ### 迭代次數 ##注意## 這裏訓練次數一般填10000到50000次
policy=steps ### 學習率策略
steps=400000,450000 ### 學習率變動步長
scales=.1,.1 ### 學習率變動因子
[convolutional]
batch_normalize=1 ### BN
filters=16 ### 卷積核數目
size=3 ### 卷積核尺寸
stride=1 ### 卷積核步長
pad=1 ### pad
activation=leaky ### 激活函數
[maxpool] ###最大池化層
size=2
stride=2
[convolutional]
batch_normalize=1
filters=32
size=3
stride=1
pad=1
activation=leaky
[maxpool]
size=2
stride=2
[convolutional]
batch_normalize=1
filters=64
size=3
stride=1
pad=1
activation=leaky
[maxpool]
size=2
stride=2
[convolutional]
batch_normalize=1
filters=128
size=3
stride=1
pad=1
activation=leaky
[maxpool]
size=2
stride=2
[convolutional]
batch_normalize=1
filters=256
size=3
stride=1
pad=1
activation=leaky
[maxpool]
size=2
stride=2
[convolutional]
batch_normalize=1
filters=512
size=3
stride=1
pad=1
activation=leaky
[maxpool]
size=2
stride=1
[convolutional]
batch_normalize=1
filters=1024
size=3
stride=1
pad=1
activation=leaky
###########
[convolutional]
batch_normalize=1
filters=256
size=1
stride=1
pad=1
activation=leaky
[convolutional]
batch_normalize=1
filters=512
size=3
stride=1
pad=1
activation=leaky
[convolutional]
size=1
stride=1
pad=1
filters=21 ##注意## 這裏更改爲(classes + 5)x3
activation=linear
[yolo]
mask = 3,4,5
anchors = 10,14, 23,27, 37,58, 81,82, 135,169, 344,319
classes=2 ###類別 ##注意## 這裏類別填你的標註類別有多少類
num=6
jitter=.3
ignore_thresh = .7
truth_thresh = 1
random=1 ###如果顯存很小,將random設置爲0,關閉多尺度訓練
[route]
layers = -4
[convolutional]
batch_normalize=1
filters=128 ###更改爲filters =(classes + 5)x3
size=1
stride=1
pad=1
activation=leaky
[upsample]
stride=2
[route]
layers = -1, 8
[convolutional]
batch_normalize=1
filters=21 ###更改爲filters =(classes + 5)x3 ##注意## 這裏更改爲(classes + 5)x3
size=3
stride=1
pad=1
activation=leaky
[convolutional]
size=1
stride=1
pad=1
filters=21 ###更改爲filters =(classes + 5)x3 ##注意## 這裏更改爲(classes + 5)x3
activation=linear
[yolo]
mask = 0,1,2
anchors = 10,14, 23,27, 37,58, 81,82, 135,169, 344,319
classes=2 ###類別 ##注意## 這裏類別填你的標註類別有多少類
num=6
jitter=.3 ### 數據擴充的抖動操作
ignore_thresh = .7 ###文章中的閾值1
truth_thresh = 1 ###文章中的閾值2
random=1 ###如果顯存很小,將random設置爲0,關閉多尺度訓練
2、訓練參數優化
在darknet目錄下創建兩個文件:voc.names 和 voc.data
voc.names文件:每一個類別單獨一行寫上去
voc.data文件:
classes = 2 #類的數目
train = /darknet/scripts/2007_train.txt #剛剛2007_train.txt的路徑
valid = /darknet/scripts/2007_test.txt #剛剛2007_test.txt的路徑
names = /darknet/voc.names #剛剛voc.names文件的路徑
backup = /darknet/backup #到時候訓練出來模型權重所在文件夾
五、開始訓練
1、下載預訓練權重文件
wget http://pjreddie.com/media/files/darknet53.conv.74
2、在darknet中打開終端輸入\以下命令即可開始訓練
./darknet detector train voc.data cfg/yolov3-tiny.cfg darknet53.conv.74
六、訓練過程中參數含義
- Region xx: cfg文件中yolo-layer的索引;
- Avg IOU:當前迭代中,預測的box與標註的box的平均交併比,越大越好,期望數值爲1;
- Class: 標註物體的分類準確率,越大越好,期望數值爲1;
- obj: 越大越好,期望數值爲1;
- No obj: 越小越好;
- .5R: 以IOU=0.5爲閾值時候的recall; recall = 檢出的正樣本/實際的正樣本
- 0.75R: 以IOU=0.75爲閾值時候的recall;
- count:正樣本數目。
七、訓練小竅門
1、斷點重新訓練
如果從某次斷了重新開始訓練,只需要把 darknet53.conv.74 換成你的某一次的weights即可
例如:把命令行中的參數 darknet53.conv.74 改成 yolov3-tiny_1000.weights 即可
2、修改cfg/xxx.cfg,首先修改分類數爲自己的分類數,然後注意開頭部分訓練的batchsize和subdivisions被註釋了,如果需要自己訓練的話就需要去掉,測試的時候需要改回來,最後可以修改動量參數爲0.99和學習率改小,這樣可以避免訓練過程出現大量nan的情況,最後把每個[yolo]前的filters改成18這裏怎麼改具體可以看這個issule:https://github.com/pjreddie/darknet/issues/582, 改完之後就可以訓練我們的模型了
3、若出現顯存不足,可修改batch的大小和取消random多尺度,默認情況下random=1,取消將random=0,一共在3處地方。