yolov3訓練


作者:ll_sunsmile
來源:CSDN
原文:https://blog.csdn.net/ll_master/article/details/81392013
版權聲明:本文為博主原創文章,轉載請附上博文鏈接!

列舉問題:

(1、2、3在test中出現,4在train中出現)

1.

改darknet下makefile文件參數,修改不成功。
解決:服務器配置有問題。檢查cuda,cudnn,opencv這些版本是否兼容吧。。要是一直修改不成功,就去刪darknet,重新做一遍。要出來結果,肯定要付出代價的么。一遍不成功就再來一遍。反正我改了修也做了三遍。

2.

backup生成的權重文件不會用。傻里巴嘰還用之前自帶版本的權重,結果哭唧唧,生成一大堆車、馬、人,根本不是自己需要的類別標簽。
解決:當然使用自己生成的權重文件啦,backup下每次都有會新的迭代權重。

3

好不容易解決了前面兩個,終於熬到檢測這一步,奇怪的發現還是什么都沒有。
解決:檢測語句有問題,細心的我特別去看了官網的檢測語句。有兩條等同的檢測語句,我們選擇那條指明分類的語句。因為分類結果出不來,肯定是沒有找到分類文件呀。我們給他指明,就清楚咯。
選擇這種:

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

不選擇這種:

./darknet detect cfg/yolov3-voc.cfg backup/yolov3-voc_600.weights data/1.jpg

4.

還有就是開始train的時候cuda out of memory等問題。
例如 :

0 CUDA Error: out of memory 
darknet: ./src/cuda.c:36: check_error: Assertion `0’ failed.

原因:gpu占用有問題,gpu全部占用,或內存不足時會出現此問題。
解決方案1:修改batch=1與subdivision=1,減少每次的輸入量。
解決方案2:查看GPU占用,

nvidia-smi	#查看GPU占用情況,
kill -9 <pid>	#-9,強制執行

訓練正式開始

1.

標注自己的數據集。根據自己划分的類別用labelimg進行標注,保存后會生成與所標注圖片文件名相同的xml文件。

2.

下載官網yolov3工程

git clone https://github.com/pjreddie/darknet cd darknet
cd darknet

3.

修改配置文件
打開Makefile,修改編譯選擇。

  1. GPU=1 #使用GPU訓練,其他參數可根據需要調整
  2. CUDNN=0 #可選
  3. OPENCV=1 #需安裝opencv
  4. OPENMP=0
  5. DEBUG=0
make #保存,記住一定要make才能生效 

修改完成后,在darknet目錄下進行編譯。
如果服務器配置沒有問題,那么會成功,如果不成功的話就檢查一下cuda,cudnn,opencv這些版本是否兼容的問題。

4.

准備數據集,建立層級結構存儲目錄便於數據的管理。文件名稱的命名也是為了以后方便修改配置文件。

  1. darknet
  2. --voc
  3. ​ --VOCdevkit
  4. ​ --VOC2018 #voc%s 這個%s最好是按照自己的數據集名稱命名,為了以后區分自己數據集。
  5. ​ --Annotations
  6. ​ --ImageSets
  7. ​ --Main
  8. ​ --JPEGImages

Annotations中放所有的xml文件;JPEGImages中放所有的圖片;Main中放train.txt和test.txt。

5.

然而train.txt和test.txt是如何生成的呢?
生成python文件取出訓練集和測試集的圖片名稱沒有后綴名。

import os
from os import listdir, getcwd
from os.path import join
if __name__ == '__main__':
    source_folder='/home/lll/darknet/voc/VOCdevkit/VOC2018/JPEGImages/'#地址是所有圖片的保存地點
    dest='/home/lll/darknet/voc/VOCdevkit/VOCClock/ImageSets/Main/train.txt'  #保存train.txt的地址
   dest2='/home/lll/darknet/voc/VOCdevkit/VOCClock/ImageSets/Main/test.txt'  #保存val.txt的地址
    file_list=os.listdir(source_folder)       #賦值圖片所在文件夾的文件列表
    train_file=open(dest,'a')                 #打開文件
    val_file=open(dest2,'a')                  #打開文件
    for file_obj in file_list:                #訪問文件列表中的每一個文件
        file_path=os.path.join(source_folder,file_obj) 
        #file_path保存每一個文件的完整路徑
        file_name,file_extend=os.path.splitext(file_obj)
        #file_name 保存文件的名字,file_extend保存文件擴展名
        file_num=int(file_name) 
        #把每一個文件命str轉換為 數字 int型 每一文件名字都是由四位數字組成的  如 0201 代表 201     高位補零  
        if(file_num<150):                     #保留149個文件用於訓練
            #print file_num
            train_file.write(file_name+'\n')  #用於訓練前149個的圖片路徑保存在train.txt里面,結尾加回車換行
        else :
            val_file.write(file_name+'\n')    #其余的文件保存在val.txt里面
    train_file.close()#關閉文件
val_file.close()

6.

下載和修改voc_label.py(這個文件就說明了為什么一開始建立層級目錄,因為可以避免很多路徑的修改呀)
下載:
wget https://pjreddie.com/media/files/voc_label.py
修改:

import xml.etree.ElementTree as ET
import pickle
import os
from os import listdir, getcwd
from os.path import join
 #根據自己的需要修改,只要前后路徑對應就行。
sets=[('2018', 'train'), ('2018', 'test')]
 #我的類是5個(^U^)ノ~YO
classes = ["m", "s","l","xl","xxl"]
def convert(size, box):
    dw = 1./size[0]
    dh = 1./size[1]
    x = (box[0] + box[1])/2.0
    y = (box[2] + box[3])/2.0
    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()

7.

執行voc_label.py:

python voc_label.py

在voc下生成了2018_train.txt 和 2018_test.txt,分別存放了訓練集和測試集圖片的路徑。
ps:這里用到了之前main下的train和test文本文件,使得xml和jpg文件一一對應,並且生成最后的圖片路徑。
之后訓練時候就可以根據圖片路徑和一些配置文件信息進行訓練咯。

8.

下載預訓練模型

wget https://pjreddie.com/media/files/darknet53.conv.74

9.

修改 cfg/voc.data

  1. classes= 5 #classes為訓練樣本集的類別總數
  2. train = /home/lll/darknet/voc/2018_train.txt #train的路徑為訓練樣本集所在的路徑
  3. valid = /home/lll/darknet/voc/2018_test.txt #test的路徑為驗證樣本集所在的路徑
  4. names = data/voc.names #names的路徑為data/voc.names文件所在的路徑
  5. backup = backup

10.

修改data/voc.names

  • s
  • m
  • l
  • xl
  • xxl
  • 上面python文件中也要與之對應哈

11.

修改cfg/yolov3-voc.cfg

[net]
#Testing
#batch=1
#subdivisions=1
#Training
 batch=64            
 subdivisions=8    #---------------修改
......
[convolutional]
size=1
stride=1
pad=1
filters=30        #---------------修改
activation=linear
[yolo]
mask = 6,7,8
anchors = 10,13,  16,30,  33,23,  30,61,  62,45,  59,119,  116,90,  156,198,  373,326
classes=5        #---------------修改
num=9
jitter=.3
ignore_thresh = .5
truth_thresh = 1
random=0            #---------------修改
......
[convolutional]
size=1
stride=1
pad=1
filters=30        #---------------修改
activation=linear
[yolo]
mask = 3,4,5
anchors = 10,13,  16,30,  33,23,  30,61,  62,45,  59,119,  116,90,  156,198,  373,326
classes=5        #---------------修改
num=9
jitter=.3
ignore_thresh = .5
truth_thresh = 1
random=0        #---------------修改
......
[convolutional]
size=1
stride=1
pad=1
filters=30        #---------------修改
activation=linear
[yolo]
mask = 0,1,2
anchors = 10,13,  16,30,  33,23,  30,61,  62,45,  59,119,  116,90,  156,198,  373,326
classes=5        #---------------修改
num=9
jitter=.3
ignore_thresh = .5
truth_thresh = 1
random=0        #---------------修改
標記的地方需要修改,classes是你的分類數,filters=3*(classes+5),random=0即關閉多尺度訓練

具體每個參數的意思,我會繼續更新總結的。怎么調整參數,使得效果最佳,還要依靠人為經驗。

12.

開始訓練:

./darknet detector train cfg/voc.data cfg/yolov3-voc.cfg darknet53.conv.74 -gpus 0,1,2,3

開始測試

./darknet detector test  cfg/voc.data cfg/yolov3-voc.cfg backup/yolov3-voc_900.weights  voc/VOCdevkit/VOC2018/test/169.jpg

測試權重用自己生成的backup下的,測試照片用自己測試集的。
希望可愛的你也會出現自己想要的結果哦!!

參數解釋

還想解釋一下訓練過程中出現的種種參數,那都是是個啥?來來來,看一看。
參考一下
原英文地址: https://timebutt.github.io/static/understanding-yolov2-training-output/
原中文翻譯地址:https://blog.csdn.net/dcrmg/article/details/78565440
8個分組,因此有八個subdivision,每個subdivision有八個照片
以上截圖顯示了所有訓練圖片的一個批次(batch),批次大小的划分根據我們在 .配置cfg 文件中設置的subdivisions參數。修改的cfg 文件中 batch = 64 ,subdivision = 8,所以在訓練輸出中,訓練迭代包含了8組,每組又包含了8張圖片,跟設定的batchsubdivision的值一致。
Region Avg IOU: 0.326577: 表示在當前subdivision內的圖片的平均IOU,代表預測的矩形框和真實目標的交集與並集之比,這里是32.66%,這個模型需要進一步的訓練。
Class: 0.742537: 標注物體分類的正確率,期望該值趨近於1。
Obj: 0.033966: 越接近1越好。
No Obj: 0.000793: 期望該值越來越小,但不為零。
Avg Recall: 0.12500: 是在recall/count中定義的,是當前模型在所有subdivision圖片中檢測出的正樣本與實際的正樣本的比值。在本例中,只有八分之一的正樣本被正確的檢測到。(和最開始初定的閾值有關系)
count: 8:count后的值是所有的當前subdivision圖片(本例中一共8張)中包含正樣本的圖片的數量。在輸出log中的其他行中,可以看到其他subdivision也有的只含有6或7個正樣本,說明在subdivision中含有不含檢測對象的圖片。
9798: 指示當前訓練的迭代次數
0.370096: 是總體的Loss(損失)
0.451929 avg: 是平均Loss,這個數值應該越低越好,一般來說,一旦這個數值低於0.060730 avg就可以終止訓練了。
0.001000 rate: 代表當前的學習率,是在.cfg文件中定義的。
3.300000 seconds: 表示當前批次訓練花費的總時間。
627072 images: 這一行最后的這個數值是9798*64的大小,表示到目前為止,參與訓練的圖片的總量。

作者:ll_sunsmile
來源:CSDN
原文:https://blog.csdn.net/ll_master/article/details/81392013
版權聲明:本文為博主原創文章,轉載請附上博文鏈接!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM