YoloV4訓練自己的資料集
- 1-建立作業檔案夾
- 2-準備訓練資料集
- 3 修改組態檔
- 4-訓練自己的資料集
- 5-測驗訓練出來的網路模型
- 6-性能統計
- 7-Anchor Box先驗框聚類分析與修改
1-建立作業檔案夾
新建一個專案檔案夾,用于存放接下來訓練所需要的檔案,
mkdir train # 或者其他英文名
切換至作業檔案夾
cd train
按照下圖所示建立相關檔案夾和檔案,
.
├── JPEGImages
├── Annotations
├── labels
├── backup
├── data
│ ├── train.data
│ ├── train.names
│ ├── yolov4.cfg
│ ├── yolov4-tiny.cfg
├── darknet
├── gen_files.py
├── yolov4.conv.137
├── yolov4-tiny.conv.29
| 檔案/檔案夾 | 作用 |
|---|---|
| JPEGImages | 用于存放訓練需要使用的圖片 |
| Annotations | 用于存放訓練圖片對應的XML標注檔案 |
| labels | 用于存放YOLO格式的txt標注檔案 |
| backup | 用于存放訓練出來的模型檔案 |
| data | 用于存放模型訓練需要的一些引數檔案 |
| 檔案 | 作用 | 如何獲取 |
|---|---|---|
| darknet | darknet可執行檔案 | 編譯darknet后,將darknet可執行檔案拷貝進來 |
| gen_files.py | 用于對訓練圖片和標注進行處理歸檔 | 見下面的gen_files.py檔案內容 |
| yolov4.conv.137 | yolov4在coco資料集上的預訓練權重檔案(不含yolo head層) | 自行下載 |
| yolov4-tiny.conv.29 | yolov4-tiny在coco資料集上的預訓練權重檔案(不含yolo head層) | 自行下載 |
| train.data | 訓練資料 | 自行建立,一會在里面添加文本內容 |
| train.names | 訓練的標簽 | 自行建立,一會在里面添加文本內容 |
| yolov4.cfg | 訓練YoloV4需要的結構檔案 | 在darknet專案的cfg檔案夾里,拷貝進來即可 |
| yolov4-tiny.cfg | 訓練YoloV4-Tiny需要的結構檔案 | 在darknet專案的cfg檔案夾里,拷貝進來即可 |
gen_files.py內容如下:
import xml.etree.ElementTree as ET
import pickle
import os
from os import listdir, getcwd
from os.path import join
import random
# 類別串列
classes=["ball"]
# 遞回清除Linux隱藏檔案
def clear_hidden_files(path):
dir_list = os.listdir(path)
for i in dir_list:
abspath = os.path.join(os.path.abspath(path), i)
if os.path.isfile(abspath):
if i.startswith("._"):
os.remove(abspath)
else:
clear_hidden_files(abspath)
# PASCAL VOC格式的xml標注檔案 轉換為 YOLO格式的txt文本標注檔案
def convert(size, box):
'''
size = (w, h)
box = (xmin, xmax, ymin, ymax)
'''
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(image_id):
in_file = open('Annotations/%s.xml' %image_id)
out_file = open('labels/%s.txt' %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')
in_file.close()
out_file.close()
# 當前目錄
wd = os.getcwd()
# 檢查是否存在Annotations檔案夾
annotation_dir = os.path.join(wd, "Annotations/")
if not os.path.isdir(annotation_dir):
os.mkdir(annotation_dir)
# 清除隱藏檔案
clear_hidden_files(annotation_dir)
# 檢查是否存在JPEGImages檔案夾
image_dir = os.path.join(wd, "JPEGImages/")
if not os.path.isdir(image_dir):
os.mkdir(image_dir)
# 清除隱藏檔案
clear_hidden_files(image_dir)
# 檢查是否存在backup檔案夾
backup_dir = os.path.join(wd, "backup/")
if not os.path.isdir(backup_dir):
os.mkdir(backup_dir)
# 清除隱藏檔案
clear_hidden_files(backup_dir)
# 檢查是否存在labels檔案夾
labels_dir = os.path.join(wd, "labels/")
if not os.path.isdir(labels_dir):
os.mkdir(labels_dir)
# 清除隱藏檔案
clear_hidden_files(labels_dir)
# 新建檔案train.txt、test.txt
# 存放需要訓練和測驗的完整檔案路徑
train_file = open(os.path.join(wd, "train.txt"), 'w')
test_file = open(os.path.join(wd, "test.txt"), 'w')
train_file.close()
test_file.close()
# 訓練資料集
train_file = open(os.path.join(wd, "train.txt"), 'a')
# 測驗資料集
test_file = open(os.path.join(wd, "test.txt"), 'a')
# 列出所有圖片檔案
list = os.listdir(image_dir)
# 設定訓練集/測驗集劃分比例的亂數
probo = random.randint(1, 100)
print("Probobility: %d" % probo)
for i in range(0,len(list)):
path = os.path.join(image_dir,list[i])
if os.path.isfile(path):
image_path = image_dir + list[i]
# 根據檔案名,得到沒有后綴的檔案名和后綴名
(nameWithoutExtention, extention) = os.path.splitext(os.path.basename(image_path))
# 標注檔案名
annotation_name = nameWithoutExtention + '.xml'
# 標注檔案地址
annotation_path = os.path.join(annotation_dir, annotation_name)
# 設定訓練集/測驗集劃分比例的亂數
probo = random.randint(1, 100)
print("Probobility: %d" % probo)
# 訓練集和測驗集的劃分,這里的75代表訓練集/測驗集的劃分比例為75:25
# 訓練集
if(probo < 75):
if os.path.exists(annotation_path):
# 在當前目錄下的train.txt文本檔案中,寫入訓練圖片的完整地址
train_file.write(image_path + '\n')
# 執行標注格式轉換
convert_annotation(nameWithoutExtention)
# 測驗集
else:
if os.path.exists(annotation_path):
# 在當前目錄下的test.txt文本檔案中,寫入訓練圖片的完整地址
test_file.write(image_path + '\n')
# 執行標注格式轉換
convert_annotation(nameWithoutExtention)
# 檔案操作結束后,關閉檔案流
train_file.close()
test_file.close()
2-準備訓練資料集
2-1 將訓練所需的圖片拷貝至JPEGImages檔案夾下,
2-2 將訓練圖片對應的XML標注檔案拷貝至Annotations下,
確保
labels檔案夾下沒有檔案及隱藏檔案
確保訓練圖片和標注一一對應
2-3 修改gen_files.py中的classes為自己的標簽,
例如:
classes = ["person", "phone", "chair"]
有幾個標簽修改為幾個,
2-4 在終端運行gen_files.py
python3 gen_files.py
此時會在當前訓練檔案夾生成文本檔案train.txt和test.txt,
labels檔案夾下會生成YOLO格式的txt標注檔案,
train.txt檔案內容為訓練集圖片的絕對地址的集合,一行一條,
test.txt檔案內容為測驗集圖片的絕對地址的集合,一行一條,
可以看到train.txt和test.txt中的條目數的比例大致為之前設定的75:25,
當然也可以設定為其他的訓練集/測驗集劃分比例,
labels下的檔案是JPEGImages檔案夾下每一個影像的YOLO格式的標注檔案,這是由Annotations檔案夾的xml標注檔案轉換來的,
最終訓練只需要:
train.txttest.txtlabels檔案夾下的txt文本標注檔案JPEGImages檔案夾下的影像檔案
此時訓練檔案夾的目錄樹如下所示:
.
├── JPEGImages
├── Annotations
├── labels
├── backup
├── data
│ ├── train.data
│ ├── train.names
│ ├── yolov4.cfg
│ ├── yolov4-tiny.cfg
├── darknet
├── gen_files.py
├── yolov4.conv.137
├── yolov4-tiny.conv.29
├── train.txt
├── test.txt
新增train.txt、test.txt,
labels檔案夾下新增n個YOLO格式的txt標注檔案,
3 修改組態檔
3-1 新建data/train.names檔案
可以復制darknet目錄下的data/voc.names到訓練目錄下的data/train.names,
再根據自己情況的修改,可以重新命名如:data/train.names,
names檔案存放訓練的標簽,一行一個標簽,不要有空行,
例如3個標簽的情況下,可以修改為:
person
phone
chair
替換為自己訓練的標簽即可,
3-2 新建data/train.data檔案
可以復制darknet目錄下的cfg/coco.data到訓練目錄下的data/train.data,
再根據自己情況的修改,可以重新命名如:data/train.data,
data檔案存放類別數、訓練集位置、測驗集位置、names檔案位置、訓練出來的模型的存放地址等資訊,
例如:
classes = 80
train = train.txt
valid = test.txt
#valid = data/coco_val_5k.list
names = data/train.names
backup = backup
eval = coco
這里的檔案地址都是相對于訓練作業檔案夾的,
| 引數名 | 作用 |
|---|---|
| classes | 類別數,標注、訓練了幾個類別,就寫幾 |
| train | 訓練集train.txt的檔案地址 |
| valid | 測驗集test.txt的檔案地址 |
| names | names標簽檔案的檔案地址 |
| backup | 訓練出來的模型的存放檔案夾 |
| eval | 評估引數(暫時沒有搞明白) |
3-3和3-4二選一,看需要訓練的模型是YoloV4還是YoloV4-Tiny,
3-3 新建data/yolov4-tiny.cfg
可以復制darknet目錄下的cfg/yolov4-tiny.cfg到訓練目錄下的yolov4-tiny.cfg,
再根據自己情況的修改,可以重新命名data/yolov4-tiny-xxx.cfg,
batch = 64
subdivisions = 32
在data/yolov4-tiny.cfg檔案中,兩個yolo層和各自前面的convolutional層的引數需要修改:
- 兩個
yolo層都要改:yolo層中的classes為類別數 - 每一個
yolo層前的convolutional層中的filters =(類別+5)* 3
例如:
yolo層:classes=1;convolutional層:filters=18
yolo層:classes=2; convolutional層:filters=21
yolo層:classes=4;convolutional層:filters=27
3-4 新建data/yolov4.cfg
可以復制darknet目錄下的cfg/yolov4.cfg到訓練目錄下的yolov4.cfg,
再根據自己情況的修改,可以重新命名data/yolov4-xxx.cfg,
batch = 64
subdivisions = 32
在data/yolov4.cfg檔案中,兩個yolo層和各自前面的convolutional層的引數需要修改:
- 兩個
yolo層都要改:yolo層中的classes為類別數 - 每一個
yolo層前的convolutional層中的filters =(類別+5)* 3
例如:
yolo層:classes=1;convolutional層:filters=18
yolo層:classes=2; convolutional層:filters=21
yolo層:classes=4;convolutional層:filters=27
4-訓練自己的資料集
4-1 確保yolov4-tiny.conv.29或者yolov4.conv.137在訓練檔案夾下
4-2 開始訓練
訓練命令:
./darknet detector train data檔案地址 cfg檔案地址 預訓練權重檔案(不含yolo head層) -map
如需無須顯示訓練程序的map變化,在命令末尾加-map,即:
./darknet detector train data/train.data data/yolov4-tiny.cfg yolov4-tiny.conv.29
如需要顯示訓練程序的map變化,在命令末尾加-map,即:
./darknet detector train data/train.data data/yolov4-tiny.cfg yolov4-tiny.conv.29 -map
對于YoloV4模型的訓練,只需要把命令里的cfg組態檔和預訓練權重檔案替換為YoloV4版本的就可以,
4-3 訓練建議
batch=64subdivisions=4(或2,1)- YOLOv4: 把
max_batches設定為 (classes*2000);但最小為4000, YOLOv4-tiny可減少 - YOLOv4: 把
steps改為max_batches的80% and 90%;例如steps=3200, 3600,YOLOv4-tiny可相應減少 - 為增加網路解析度可增大
height和width的值,但必須是32的倍數 (height=608, width=608或者是32的整數倍) ,這有助于提高檢測精度
5-測驗訓練出來的網路模型
訓練好后可以在backup目錄下看到權重檔案,
測驗圖片
./darknet detector test data/train.data data/yolov4-tiny.cfg backup/yolov4-tiny_best.weights xxx.jpg
測驗視頻
./darknet detector demo data/train.data data/yolov4-tiny.cfg backup/yolov4-tiny_best.weights xxx.mp4
6-性能統計
模型的性能主要體現在:mAP
6-1 統計 mAP@IoU=0.50:
./darknet detector map data/train.data data/yolov4-tiny.cfg backup/yolov4-tiny_best.weights
6-2 統計 mAP@IoU=0.75:
./darknet detector map data/train.data data/yolov4-tiny.cfg backup/yolov4-tiny_best.weights -iou_thresh 0.75
7-Anchor Box先驗框聚類分析與修改
7-1 使用k-means聚類獲得自己資料集的先驗框大小
對于YoloV4-Tiny:
./darknet detector calc_anchors data/train.data -num_of_clusters 6 -width 416 -height 416
對于YoloV4:
./darknet detector calc_anchors data/train.data -num_of_clusters 9 -width 416 -height 416
7-2 修改cfg檔案中的先驗框大小
cfg檔案中的anchors位置的幾個數字
7-3 重新訓練和測驗
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/224272.html
標籤:python
