YOLO v3——訓練自己的VOC數據及訓練技巧

目錄

 

一、安裝darknet

二、編譯(這裏直接安裝cpu版本作爲例子)

三、製作數據集

四、修改訓練配置文件

五、開始訓練

六、訓練過程中參數含義

七、訓練小竅門


一、安裝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

六、訓練過程中參數含義

  1. Region xx: cfg文件中yolo-layer的索引;
  2. Avg IOU:當前迭代中,預測的box與標註的box的平均交併比,越大越好,期望數值爲1;
  3. Class: 標註物體的分類準確率,越大越好,期望數值爲1;
  4. obj: 越大越好,期望數值爲1;
  5. No obj: 越小越好;
  6. .5R: 以IOU=0.5爲閾值時候的recall; recall = 檢出的正樣本/實際的正樣本
  7. 0.75R: 以IOU=0.75爲閾值時候的recall;
  8. 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處地方。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章