YOLOV5介紹
YOLOV5是目前最火熱的目標檢測算法之一。YOLOV5為一階段檢測算法因此它的速度非常之快??梢栽趶?fù)雜場景中達到60禎的實時檢測頻率。
接下來本文將詳細的講述如何使用YOLOV5去訓(xùn)練自己的數(shù)據(jù)集
一、下載YOLOv5開源代碼
$ git clone https://github.com/ultralytics/yolov5.git
$ cd yolov5
$ pip install -r requirements.txt
YOLOV5中使用了Tensorboard和Wandb來可視化訓(xùn)練,其中Wandb配置可以看這篇文章:
Wandb安裝與配置
二、構(gòu)建YOLO數(shù)據(jù)集
數(shù)據(jù)集地址:MaskDetecion
下載好數(shù)據(jù)集之后將數(shù)據(jù)集解壓到Y(jié)OLOV5項目文件夾下的DataSets目錄下(需要先新建一個DataSets文件夾)
劃分數(shù)據(jù)集
將數(shù)據(jù)集劃分為訓(xùn)練集、驗證集、測試集:
# coding:utf-8
#劃分數(shù)據(jù)集
import os
import random
import argparse
parser = argparse.ArgumentParser()
#xml文件的地址,根據(jù)自己的數(shù)據(jù)進行修改 xml一般存放在Annotations下
parser.add_argument('--xml_path', default='./DataSets/annotations', type=str, help='xml path')
#數(shù)據(jù)集劃分后txt文件的存儲地址,地址選擇自己數(shù)據(jù)下的ImageSets/Main
parser.add_argument('--txt_path', default='./DataSets/ImageSets/Main', type=str, help='output txt label path')
opt = parser.parse_args()
trainval_percent = 0.9 #訓(xùn)練集和驗證集的比例
train_percent = 0.9 #訓(xùn)練集占總數(shù)據(jù)的比例
imgfilepath = opt.img_path
txtsavepath = opt.txt_path
total_xml = os.listdir(imgfilepath)
if not os.path.exists(txtsavepath):
os.makedirs(txtsavepath)
num = len(total_xml)
list_index = range(num)
tv = int(num * trainval_percent)
tr = int(tv * train_percent)
trainval = random.sample(list_index, tv)
train = random.sample(trainval, tr)
#劃分生成的文件名稱
file_trainval = open(txtsavepath + '/trainval.txt', 'w')
file_test = open(txtsavepath + '/test.txt', 'w')
file_train = open(txtsavepath + '/train.txt', 'w')
file_val = open(txtsavepath + '/val.txt', 'w')
for i in list_index:
name = total_xml[i][:-4] + '\n'
if i in trainval:
file_trainval.write(name)
if i in train:
file_train.write(name)
else:
file_val.write(name)
else:
file_test.write(name)
file_trainval.close()
file_train.close()
file_val.close()
file_test.close()
劃分完成之后會生成以下文件:
每個txt中的內(nèi)容為xml的文件名:
生成YOLO格式的label
轉(zhuǎn)換xml為txt
import xml.etree.ElementTree as ET
import pickle
import os
from os import listdir, getcwd
from os.path import join
import shutil
#VOC生成txt的文件
sets = ['train', 'val', 'test'] #數(shù)據(jù)集,最后會生成以這三個數(shù)據(jù)集命名的txt文件
classes = ['with_mask', 'without_mask', 'mask_weared_incorrect'] #標簽名,注意一定不要出錯
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(image_id):
in_file = open('./DataSets/annotations/%s.xml' % (image_id), 'r', encoding="UTF-8")
out_file = open('./DataSets/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')
for image_set in sets:
if not os.path.exists('./DataSets/labels/'): #創(chuàng)建label文件夾
os.makedirs('./DataSets/labels/')
image_ids = open('./DataSets/ImageSets/Main/%s.txt' % (image_set)).read().strip().split()
list_file = open('./DataSets/%s.txt' % (image_set), 'w')
for image_id in image_ids:
list_file.write('S:/pythonProjects/DSA/MaskDetection/yolov5/DataSets/images/%s.png\n' % (image_id)) #這里最好用全局路徑
convert_annotation(image_id)
list_file.close()
運行結(jié)束后會生成label文件夾和劃分后三個數(shù)據(jù)集的具體文件路徑
label中是轉(zhuǎn)換出來的yolo格式數(shù)據(jù)集,分別為:標簽類別,x:中心點x值/圖片寬度,y:中心點y值/圖片高度,w:目標框的寬度/圖片寬度,h:目標框的高度/圖片高度。
詳情可參考博客:YOLO數(shù)據(jù)集標注
而生成的三個txt相當于在之前劃分的數(shù)據(jù)集上加上了路徑,方便直接讀取
新建一個數(shù)據(jù)集配置文件
在data文件夾下新建一個mask.yaml文件,用來寫數(shù)據(jù)集的一些配置,后續(xù)代碼中也是通過讀取yaml來讀取數(shù)據(jù)集
#數(shù)據(jù)集的路徑,推薦用絕對路徑
train: S:/pythonProjects/DSA/MaskDetection/yolov5/DataSets/train.txt
val: S:/pythonProjects/DSA/MaskDetection/yolov5/DataSets/val.txt
test: S:/pythonProjects/DSA/MaskDetection/yolov5/DataSets/test.txt
nc: 3 #分類個數(shù)
names: ['with_mask;', 'without_mask', 'mask_weared_incorrect'] #標簽
至此,數(shù)據(jù)集制作就結(jié)束了。
三、修改訓(xùn)練文件
修改訓(xùn)練的一些參數(shù)(由于github上項目一直在更新,不同的版本的參數(shù)可能不同,比如我最新下載這個沒有freeze這個凍結(jié)參數(shù)的選項了。但最重要的幾個一直都有)
parser = argparse.ArgumentParser()
parser.add_argument('--weights', type=str, default='yolov5s.pt', help='initial weights path')
#權(quán)重文件,在第一次訓(xùn)練時,YOLOV5提供了幾個不同的預(yù)訓(xùn)練模型,詳情:https://github.com/ultralytics/yolov5
#可以提前去官網(wǎng)下載,如果沒有提前下載也沒關(guān)系,這里只要寫上預(yù)訓(xùn)練模型的名稱,會自動調(diào)用項目中的download.sh去下載權(quán)重。
#當然也可以不使用預(yù)訓(xùn)練,這里設(shè)置為空就行;
parser.add_argument('--cfg', type=str, default='yolov5s.yaml', help='model.yaml path')
#模型參數(shù)的配置文件,里面指定了一些參數(shù)信息和backbone的結(jié)構(gòu)信息。需要跟選擇的預(yù)訓(xùn)練模型一致。
parser.add_argument('--data', type=str, default='data/mask.yaml', help='data.yaml path') #數(shù)據(jù)集地址
parser.add_argument('--hyp', type=str, default='data/hyp.scratch.yaml', help='hyperparameters path')
#模型訓(xùn)練的初始超參數(shù)文件,同樣也提供了其他訓(xùn)練的超參數(shù)文件,可以自行選擇
parser.add_argument('--epochs', type=int, default=300)
#訓(xùn)練輪數(shù),相當于0-299
parser.add_argument('--batch-size', type=int, default=16, help='total batch size for all GPUs')
#每次送入的樣本量,數(shù)據(jù)集總數(shù)/batch_size就是每一輪總共要迭代的次數(shù),越大效果越好。default=-1將時自動調(diào)節(jié)batchsize大小。
#順便說一下epoch、batchsize、iteration三者之間的聯(lián)系 1、batchsize是批次大小,假如取batchsize=24,則表示每次訓(xùn)練時在訓(xùn)練集中取24個訓(xùn)練樣本進行訓(xùn)練。 2、iteration是迭代次數(shù),1個iteration就等于一次使用24(batchsize大?。﹤€樣本進行訓(xùn)練。 3、epoch:1個epoch就等于使用訓(xùn)練集中全部樣本訓(xùn)練1次。
parser.add_argument('--img-size', nargs='+', type=int, default=[640, 640], help='[train, test] image sizes')
#resize的圖片大小,一般來說640就夠了,原圖都比較大,如果直接上原圖會導(dǎo)致過度消耗GPU資源,但如果選擇比較大的模型,也要跟著上調(diào)。
parser.add_argument('--rect', action='store_true', help='rectangular training')
#是否采用矩陣推理的方式去訓(xùn)練模型;所謂矩陣推理就是不再要求你訓(xùn)練的圖片是正方形了;矩陣推理會加速模型的推理過程,減少一些冗余信息。
parser.add_argument('--resume', nargs='?', const=True, default=False, help='resume most recent training')
#恢復(fù)訓(xùn)練:在之前訓(xùn)練的一個模型基礎(chǔ)上繼續(xù)訓(xùn)練,比如第一次訓(xùn)練了100個epoch,后續(xù)想在第一次訓(xùn)練的模型的基礎(chǔ)上繼續(xù)訓(xùn)練100個epoch則這里改成true?;蛘呤怯?xùn)練中出現(xiàn)報錯而中斷,也可以用resume繼續(xù)訓(xùn)練。
parser.add_argument('--nosave', action='store_true', help='only save final checkpoint')
#是否只保存最后一輪訓(xùn)練的模型,這個參數(shù)不推薦,因為默認的是同時保存best和last
parser.add_argument('--notest', action='store_true', help='only test final epoch')
#只在最后一輪測試(這里說的應(yīng)該是驗證);正常情況下每個epoch都會進行驗證計算mAP,但如果開啟了這個參數(shù),那么就只在最后一輪上進行測試,不建議開啟。
parser.add_argument('--noautoanchor', action='store_true', help='disable autoanchor check')
#是否禁用自動錨框;不建議改動,默認是開啟的,自動錨點的好處是可以簡化訓(xùn)練過程;yolov5中預(yù)先設(shè)定了一下錨定框,這些錨框是針對coco數(shù)據(jù)集的,其他目標檢測也適用,可以在models/yolov5.文件中查看。
#需要注意的是在目標檢測任務(wù)中,一般使用大特征圖上去檢測小目標,因為大特征圖含有更多小目標信息,因此大特征圖上的anchor數(shù)值通常設(shè)置為小數(shù)值,小特征圖檢測大目標,因此小特征圖上anchor數(shù)值設(shè)置較大。
#訓(xùn)練開始前,會自動計算數(shù)據(jù)集標注信息針對默認錨定框的最佳召回率,當最佳召回率大于等于0.98時,則不需要更新錨定框;如果最佳召回率小于0.98,則需要重新計算符合此數(shù)據(jù)集的錨定框。
parser.add_argument('--evolve', action='store_true', help='evolve hyperparameters')
#遺傳超參數(shù)進化;yolov5使用遺傳超參數(shù)進化,提供的默認參數(shù)是通過在COCO數(shù)據(jù)集上使用超參數(shù)進化得來的。由于超參數(shù)進化會耗費大量的資源和時間,所以建議大家不要動這個參數(shù)。
parser.add_argument('--bucket', type=str, default='', help='gsutil bucket')
#是否使用一些類似于阿里云之類的云盤來上傳或下載東西,一般不用設(shè)置
parser.add_argument('--cache-images', action='store_true', help='cache images for faster training')
#是否提前緩存圖片到內(nèi)存,以加快訓(xùn)練速度,推薦設(shè)置。
parser.add_argument('--image-weights', action='store_true', help='use weighted image selection for training')
#是否啟用加權(quán)圖像策略,可以解決樣本不平衡問題;開啟后會對于上一輪訓(xùn)練效果不好的圖片,在下一輪中增加一些權(quán)重;
parser.add_argument('--device', default='', help='cuda device, i.e. 0 or 0,1,2,3 or cpu')
#訓(xùn)練設(shè)備,一般電腦只有一張顯卡默認為0,但如果使用多卡的服務(wù)器進行訓(xùn)練,這里可以選擇0,1,2,3分別對應(yīng)卡號,多選就是多卡訓(xùn)練。
parser.add_argument('--multi-scale', action='store_true', help='vary img-size +/- 50%%')
#是否使用多尺度訓(xùn)練:多尺度訓(xùn)練是指設(shè)置幾種不同的圖片輸入尺度,訓(xùn)練時每隔一定iterations隨機選取一種尺度訓(xùn)練,這樣訓(xùn)練出來的模型魯棒性更強。
#多尺度訓(xùn)練在比賽中經(jīng)??梢钥吹剿碛?,是被證明了有效提高性能的方式。輸入圖片的尺寸對檢測模型的性能影響很大,在基礎(chǔ)網(wǎng)絡(luò)部分常常會生成比原圖小數(shù)十倍的特征圖,導(dǎo)致小物體的特征描述不容易被檢測網(wǎng)絡(luò)捕捉。通過輸入更大、更多尺寸的圖片進行訓(xùn)練,能夠在一定程度上提高檢測模型對物體大小的魯棒性。
parser.add_argument('--single-cls', action='store_true', help='train multi-class data as single-class')
#單分類;如果你的任務(wù)只需要檢測一個類別則這里可以設(shè)置為True
parser.add_argument('--adam', action='store_true', help='use torch.optim.Adam() optimizer')
#選擇優(yōu)化器;比如SGD,Adam,AdamW等等,默認為adam(不同版本的代碼默認不一樣)。
parser.add_argument('--sync-bn', action='store_true', help='use SyncBatchNorm, only available in DDP mode')
#是否開啟跨卡同步BN;開啟參數(shù)后即可使用 SyncBatchNorm多GPU 進行分布式訓(xùn)練
parser.add_argument('--local_rank', type=int, default=-1, help='DDP parameter, do not modify')
#DDP參數(shù),不要修改
parser.add_argument('--workers', type=int, default=8, help='maximum number of dataloader workers')
#dataloader使用多線程來加載數(shù)據(jù),提前加載未來會用到的batch數(shù)據(jù),詳情可參考:https://www.cnblogs.com/hesse-summer/p/11343870.html
parser.add_argument('--project', default='runs/train', help='save to project/name')
#訓(xùn)練文件的保存路徑,不用修改,項目中默認的保存結(jié)構(gòu)非常好看。
parser.add_argument('--entity', default=None, help='W&B entity')
#在線可視化工具,類似于tensorboard,不推薦使用,yoloV5中同時使用了Tensorboard和Wandb兩個在線可視化工具已經(jīng)非常冗余了。
parser.add_argument('--name', default='exp', help='save to project/name')
#每一輪迭代的文件夾名稱,這里不用修改,后續(xù)訓(xùn)練會自動增加:exp,exp2,exp3,exp4...
parser.add_argument('--exist-ok', action='store_true', help='existing project/name ok, do not increment')
#每次預(yù)測模型的結(jié)果是否保存在原來的文件夾;如果指定了這個參數(shù)的話,那么本次預(yù)測的結(jié)果還是保存在上一次保存的文件夾里;如果不指定就是每次預(yù)測結(jié)果保存一個新的文件夾下。
parser.add_argument('--quad', action='store_true', help='quad dataloader')
#在比默認640 大的數(shù)據(jù)集上訓(xùn)練效果更好,副作用是在 640 大小的數(shù)據(jù)集上訓(xùn)練效果可能會差一些,詳情可參考:https://blog.csdn.net/a18838956649/article/details/119020699
parser.add_argument('--linear-lr', action='store_true', help='linear LR')
#線性學(xué)習(xí)率,有的項目是cos-lr,開啟后學(xué)習(xí)率會動態(tài)的變化,推薦開啟。
parser.add_argument('--upload_dataset', action='store_true', help='Upload dataset as W&B artifact table')
#是否上傳數(shù)據(jù)集到wandb中,如果想要更好的看到數(shù)據(jù)集的情況可以開啟。
parser.add_argument('--bbox_interval', type=int, default=-1, help='Set bounding-box image logging interval for W&B')
#設(shè)置界框圖像記錄間隔,也是和wandb有關(guān),一般用不到
parser.add_argument('--save_period', type=int, default=-1, help='Log model after every "save_period" epoch')
#用于設(shè)置多少個epoch保存一下checkpoint;
parser.add_argument('--artifact_alias', type=str, default="latest", help='version of dataset artifact to be used')
#要使用的數(shù)據(jù)集工件的版本,暫時還沒看到這里的一些先關(guān)說明。
opt = parser.parse_args()
其中action='store_true’的參數(shù)默認是不開啟的,在shell只需要鍵入這個參數(shù)的名稱,不需要加值就可以開啟,這類一般是True或False的選項,如果想在編譯器中使用這個參數(shù),則可以加一個default=True
推薦參數(shù):
python train.py --weights yolov5s.pt --cfg yolov5s.yaml --data data/mask.yaml --epochs 500 --cache-images --image-weights --multi-scale --linear-lr
四、訓(xùn)練中遇到的一些報錯問題
編碼報錯
‘gbk’ codec can’t decode byte 0xaf in position 15: illegal multitype sequence
解決方案:在trian.py中這個位置的open中加上utf-8的編碼,test.py中也有這個錯誤,可以一起加上,可能是個bug,不知道官方為什么還沒改過來。
找不到數(shù)據(jù)集或標簽
AssertionError: No trains in D:\yolov5\train_data\train.cache. Can not train without trains.
AssertionError: No labels in D:\yolov5\train_data\train.cache. Can not train without labels.
這個錯誤很常見,根本原因還是數(shù)據(jù)集配置有問題,首先檢查你數(shù)據(jù)集的data.yaml里面所有路徑是否正確,其次檢查train.txt、test.txt里面的路徑是否正確,如果這些都沒問題的話那就改接下來這處地方:
在utils里面的datasets.py中搜索define找到這個函數(shù),將這里的images改成和你datasets目錄下存儲圖片的文件夾的名字一樣,比如你存儲圖片的文件夾叫JPEGImages,那么這里也要改成JPEGImages
libiomp5md.dll錯誤
這個報錯是由于anaconda下存在多個libiomp5md.dll文件導(dǎo)致的,有兩種解決方法:
- 刪除anaconda對應(yīng)環(huán)境中Libary文件夾下libiomp5md.dll文件,再運行項目時會自動生成一個libiomp5md.dll文件
- 在train.py中加上這句話,允許多個lib文件同時運行
os.environ['KMP_DUPLICATE_LIB_OK']='TRUE'
libpng warning: iCCP
libpng warning: iCCP: known incorrect sRGB profile
這個錯誤可能是由于一些圖片中存在錯誤格式,且anaconda的libpng版本過高導(dǎo)致的,解決的方法大致有兩種:
1.替換掉anaconda中的庫,詳情可以查看這篇文章并且他提供了一個不會報錯的版本。
替換anaconda中的libpng庫
2.將所有數(shù)據(jù)集中的圖片重新編碼一下,代碼如下:
import os
from tqdm import tqdm
import cv2
from skimage import io
path = r"./images/" #path后面記得加 /
fileList = os.listdir(path)
for i in tqdm(fileList):
image = io.imread(path+i) # image = io.imread(os.path.join(path, i))
image = cv2.cvtColor(image, cv2.COLOR_RGBA2BGRA)
cv2.imencode('.png',image)[1].tofile(path+i)
五、測試
測試文件為test.py,大部分參數(shù)解釋和train是一樣的,其實train.py中的驗證代碼用的就是test.py中的內(nèi)容,這里做測試的話只需要把–task這個參數(shù)改成test就行
六、訓(xùn)練、測試結(jié)果
在訓(xùn)練、測試結(jié)束后會生成很多文件,這里來大致解析一下這些文件分別是什么意思:
我的保存路徑在train下面,exp就是第一輪訓(xùn)練的結(jié)果,其中weights文件夾下面是訓(xùn)練生成的權(quán)重文件,也可以說是模型,best.pt是表現(xiàn)最好的模型,last.pt是最后一輪生成的模型
比較重要的是result.png里面是模型整體訓(xùn)練的一個情況,從這里能看到絕大部分信息。
接下來是一些分類問題的評分指標:confusion_martix.png、F1_curve.png、P_curve.png、R_curve.png、PR_curve.png
兩個參數(shù)文件:hyp.yaml/opt.yaml分別是模型的初始參數(shù)以及訓(xùn)練的初始超參數(shù)
三個events…為tensorboard的日志文件
train_batch\test_batch分別為訓(xùn)練和測試前三個batch的結(jié)果后綴為labels為標簽,pred為預(yù)測的情況,可以從這里大致看出模型的一個實際效果。
七、檢測
檢測文件為detect.py,只需要提供你想要檢測的內(nèi)容,包括圖片、視頻、調(diào)用攝像頭,這個參數(shù)為
–source,給一個路徑或者0,0為調(diào)用攝像頭
這是我實時檢測的效果,可以說還不錯
這次關(guān)于YOLOV5的訓(xùn)練步驟就結(jié)束了,如有錯誤請及時指正,后續(xù)還會繼續(xù)更新一些相關(guān)的知識,感謝觀看!文章來源:http://www.zghlxwxcb.cn/news/detail-454192.html
References
https://blog.csdn.net/xiaosangtongxue/article/details/124083959
https://zhuanlan.zhihu.com/p/549163975
https://blog.csdn.net/banyueju/article/details/91553248?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-2.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-2.control
https://qichenxi.blog.csdn.net/article/details/124234388?spm=1001.2014.3001.5506
https://blog.csdn.net/qq_44785351/article/details/127465183?spm=1001.2014.3001.5502
https://blog.csdn.net/banyueju/article/details/91553248?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-2.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-2.control文章來源地址http://www.zghlxwxcb.cn/news/detail-454192.html
到了這里,關(guān)于手把手教你如何使用YOLOV5訓(xùn)練自己的數(shù)據(jù)集的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!