darknet框架中YOLOv3對數據集進行訓練和預測詳解
1. 下載darknet源碼
在命令窗口(terminal)中進入你想存放darknet源碼的路徑,然後在該路徑下輸入依次輸入以下命令:
git clone https://github.com/pjreddie/darknet cd darknet
上述命令首先從darknet的源碼地址復制一份源碼到本地,下載下來的是一個名為darknet的文件。然後進入這個名為darknet的文件夾。
2. 修改darknet的Makefile文件
Note:如果不需要darknet在GPU上運行,則略過此步驟,隻需執行make命令。 在命令窗口輸入以下命令打開Makefile文件:
vi Makefile
將Makefile文件開頭的GPU=0改為GPU=1,如下所示:
GPU=1 CUDNN=0 OPENCV=0 OPENMP=0 DEBUG=0
修改完之後,需要執行make命令才可以生效。
make
3. 準備數據集
在./darknet/scripts文件夾下創建文件夾,命名為VOCdevkit,然後再在VOCdevkit文件夾下創建一系列文件夾,整個目錄結構如下所示:
VOCdevkit -VOC2019 # 這個文件夾的年份可以自己取 --Annotations # 在這個文件夾下存放所有的xml文件 --ImageSets ---Main # 在這個文件夾下新建兩個TXT文件 ----train.txt ----val.txt --JPEGImages # 在這個文件夾下存放所有的圖片文件
上述文件及文件夾創建好之後,下面來對我們的數據集生成train.txt和val.txt,這兩個文件中存放訓練圖像和測試圖像的文件名(不含.jpg後綴)。 新建一個creat_train_val_txt.py文件(名字可以自己隨便取),然後將以下代碼復制進去(註意相應路徑的修改)
#coding:utf-8 import os from os import listdir, getcwd from os.path import join if __name__ == '__main__': # 隻有在文件作為腳本文件直接執行時才執行下面代碼 source_folder='/home/tukrin/zhl/darknet/scripts/VOCdevkit/VOC2019/JPEGImages/' #圖片保存的路徑 dest='/home/tukrin/zhl/darknet/scripts/VOCdevkit/VOC2019/ImageSets/Main/train.txt' #寫有圖片的名字的路徑 dest2='/home/tukrin/zhl/darknet/scripts/VOCdevkit/VOC2019/ImageSets/Main/val.txt' #寫有圖片的名字的路徑 file_list=os.listdir(source_folder) #獲取各圖片的名稱 train_file=open(dest,'a') #追加寫打開 val_file=open(dest2,'a') #追加寫打開 count = 0 for file_obj in file_list: count += 1 file_path=os.path.join(source_folder,file_obj) #路徑拼接 指向 圖片文件的路徑 file_name,file_extend=os.path.splitext(file_obj) #分離文件名與擴展名 file_name為去掉擴展名的圖片名稱 # file_num=int(file_name) if(count<800): train_file.write(file_name+'\n') #寫入去掉擴展名的文件名名稱 前800個作為 訓練集數據 else : val_file.write(file_name+'\n') #寫入去掉擴展名的文件名名稱 後面的作為 驗證集數據 train_file.close() #關閉文件 val_file.close() #關閉文件
制作好creat_train_val_txt.py文件後,在命令行執行該文件:
python creat_train_val_txt.py
執行完畢之後可以看到剛剛我們新建的train.txt和val.txt文件中被寫進瞭我們的數據集圖片的文件名。
4. 修改voc_label.py
打開scripts文件夾下的 voc_label.py 文件,修改信息:#要修改的地方 共三處
import xml.etree.ElementTree as ET import pickle import os from os import listdir, getcwd from os.path import join #要修改的地方 sets=[('2019', 'train'), ('2019', 'val')] # 此處的2019對應前面新建文件夾時的2019,train和val對應兩個TXT文件的文件名 #要修改的地方 classes =["car", "people"] # 此處為數據集的類別名稱,一定要與xml文件中的類別名稱一致,有幾類就寫幾類 def convert(size, box):#size是圖片的尺寸 box是矩形的四個點 dw = 1./size[0] # 歸一化的時候就是使用寬度除以整個image_size的寬度 dh = 1./size[1] # 歸一化的時候就是使用高度除以整個image_size的高度 x = (box[0] + box[1])/2.0 # 使用(xmin+xmax)/2得到x的中心點 y = (box[2] + box[3])/2.0 # 使用(ymin+ymax)/2得到y的中心點 w = box[1] - box[0] # 然後寬度就是使用xmax-xmin計算得到 h = box[3] - box[2] # 然後高度就是使用ymax-ymin計算得到 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')#此時文件是如何形成的? open的時候自動建立 root = tree.getroot()#獲得root節點 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))#創建這個路徑 來存放txt標簽 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')#這個文件可能是自己建的? open的時候自動建立 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 2019_train.txt 2019_val.txt > train.txt") # 此處是將兩個txt連接成一個txt,如果你訓練時不用val.txt中的數據,可以註釋掉這句話。 # os.system("cat 2007_train.txt 2007_val.txt 2007_test.txt 2012_train.txt 2012_val.txt > train.all.txt")# 另外,刪除另外一條os.system(...)語句。
保存修改後,運行該文件:
python voc_label.py
執行完畢之後,會生成2018_train.txt、2018_val.txt、train.txt 三個文件,如下圖:
在labels文件夾下會生成圖片對應的txt形式的圖片標註信息
5. 下載預訓練模型
為瞭加速訓練過程,可以在darknet官網上下載預訓練模型,在該預訓練模型上再進行訓練。 在命令窗口輸入以下命令:
wget https://pjreddie.com/media/files/darknet53.conv.74
文件保存在script文件夾下即可
6. 修改./darknet/cfg/voc.data文件
classes= 2 # 你的數據集的類別數 train = /home/tukrin/zhl/darknet/scripts/2019_train.txt # 第4步中生成的txt文件路徑 valid = /home/tukrin/zhl/darknet/scripts/2019_val.txt # 第4步中生成的txt文件路徑 names = /home/tukrin/zhl/darknet/data/voc.names # voc.names 的文件路徑 backup = /home/tukrin/zhl/darknet/backup/ #backup文件夾的路徑 訓練的權重將保存在這
7. 修改./darknet/data/voc.name文件
將voc.name文件做如下修改:
car people
內容為你的數據集的類別名稱,註意和xml文件中的類別名稱一致。
8. 修改./darknet/cfg/yolov3-voc.cfg文件
該文件為網絡結構文件。 首先修改開頭處如下:
[net] # Testing # batch=1 # subdivisions=1 # Training batch=64 subdivisions=16
即,將訓練模式打開,將測試模式的語句註釋掉。
其中subdivisions為將一個batch(此處為64)分成多大的小batch。如果訓練時提示超出內存,則可以相應的改小這兩個參數的值。
接著視情況修改開頭處的超參數(學習率,迭代次數等):
width=416 height=416 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 = 50200 # 迭代次數 policy=steps steps=40000,45000 # 在指定迭代次數時進行學習率衰減 scales=.1,.1 # 學習率衰減率 此處是0.1
然後再該文件的底部部分,找到如下語句進行如下修改:
...... [convolutional] size=1 stride=1 pad=1 filters=21 ....................# 修改為 3 * (類別數 + 5),此處類別數為2,所以設置為 3*(2+5)=21 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=2 .....................# 修改類別數 num=9 jitter=.3 ignore_thresh = .5 truth_thresh = 1 random=1 ...... [convolutional] size=1 stride=1 pad=1 filters=21 .....................# 同上 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=2 .....................# 同上 num=9 jitter=.3 ignore_thresh = .5 truth_thresh = 1 random=1 ...... [convolutional] size=1 stride=1 pad=1 filters=21 .....................# 同上 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=2 .....................# 同上 num=9 jitter=.3 ignore_thresh = .5 truth_thresh = 1 random=1
有三處[yolo]的上面的[convolutional]的filters要改 和[yolo]的classes要改開始訓練
9. 開始訓練
在 ./darknet 目錄下,在命令窗口中執行以下命令,其中 -gpus 0, 1 用來指定參與訓練的GPU編號,可以省略。填0 或1
./darknet detector train cfg/voc.data cfg/yolov3-voc.cfg scripts/darknet53.conv.74 -gpus 0,1
10.訓練終止後繼續訓練方法
假如訓練由於意外情況,如顯存不夠終止瞭,可以通過加載中間權重文件,進而繼續訓練 中間權重文件在backup文件夾中
把9步權重文件的路徑換為backup中文件即可
./darknet detector train cfg/voc.data cfg/yolov3-voc.cfg backup/yolov3-voc_900.weights -gpus 0,1
backup裡文件保存規則: 訓練1000次之前每100次保存一次。所以上面圖片出現瞭100~900的權重中間文件。 訓練1000次之後每10000次保存一次。 yolov3-voc.backup 會保持100整數倍的訓練結果。 所以在1000次之後想繼續訓練的話應該加載 yolov3-voc.backup文件。註意此文件不能作為檢查模型使用。
以上就是darknet框架中YOLOv3對數據集進行訓練和預測詳解的詳細內容,更多關於darknet YOLOv3數據集訓練預測的資料請關註WalkonNet其它相關文章!
推薦閱讀:
- opencv調用yolov3模型深度學習目標檢測實例詳解
- opencv-python+yolov3實現目標檢測
- Python Flask搭建yolov3目標檢測系統詳解流程
- docker images本地遷移的實現
- 基於Pytorch版yolov5的滑塊驗證碼破解思路詳解