導(dǎo)讀
一個使用YoloV5的深度指南,使用WBF進(jìn)行性能提升。
網(wǎng)上有大量的YoloV5教程,本文的目的不是復(fù)制內(nèi)容,而是對其進(jìn)行擴展。我最近在做一個目標(biāo)檢測競賽,雖然我發(fā)現(xiàn)了大量創(chuàng)建基線的教程,但我沒有找到任何關(guān)于如何擴展它的建議。此外,我想強調(diào)一下YoloV5配置中影響性能的最重要部分,因為畢竟數(shù)據(jù)科學(xué)主要是關(guān)于實驗和超參數(shù)調(diào)整。
在這之前,我想說使用目標(biāo)檢測模型和使用圖像分類模型在框架和庫的工作方式上是不同的。這是我注意到的,我花了很長時間才弄明白。大多數(shù)流行的目標(biāo)檢測模型(如YoloV5、EfficientDet)使用命令行接口來訓(xùn)練和評估,而不是使用編碼方法。這意味著,你所需要做的就是獲取特定格式的數(shù)據(jù)(COCO或VOC),并將命令指向它。這通常與使用代碼訓(xùn)練和評估模型的圖像分類模型不同。
數(shù)據(jù)預(yù)處理
YoloV5期望你有兩個目錄,一個用于訓(xùn)練,一個用于驗證。在這兩個目錄中,你需要另外兩個目錄,“Images”和“Labels”。Images包含實際的圖像,每個圖像的標(biāo)簽都應(yīng)該有一個帶有該圖像標(biāo)注的.txt文件,文本文件應(yīng)該有與其對應(yīng)的圖像相同的名稱。
標(biāo)注格式如下:
<'class_id'><'x_center'><'y_center'>
要在代碼中做到這一點,你可能需要一個類似的函數(shù),在原始數(shù)據(jù)幀中有圖像項,它們的類id和它們的邊界框:
defcreate_file(df,split_df,train_file,train_folder,fold): os.makedirs('labels/train/',exist_ok=True) os.makedirs('images/train/',exist_ok=True) os.makedirs('labels/val/',exist_ok=True) os.makedirs('images/val/',exist_ok=True) list_image_train=split_df[split_df[f'fold_{fold}']==0]['image_id'] train_df=df[df['image_id'].isin(list_image_train)].reset_index(drop=True) val_df=df[~df['image_id'].isin(list_image_train)].reset_index(drop=True) fortrain_imgintqdm(train_df.image_id.unique()): withopen('labels/train/{train_img}.txt','w+')asf: row=train_df[train_df['image_id']==train_img] [['class_id','x_center','y_center','width','height']].values row[:,1:]/=SIZE#Imagesize,512here row=row.astype('str') forboxinrange(len(row)): text=''.join(row[box]) f.write(text) f.write(' ') shutil.copy(f'{train_img}.png', f'images/train/{train_img}.png') forval_imgintqdm(val_df.image_id.unique()): withopen(f'{labels/val/{val_img}.txt','w+')asf: row=val_df[val_df['image_id']==val_img] [['class_id','x_center','y_center','width','height']].values row[:,1:]/=SIZE row=row.astype('str') forboxinrange(len(row)): text=''.join(row[box]) f.write(text) f.write(' ') shutil.copy(f'{val_img}.png', f'images/val/{val_img}.png')
注意:不要忘記保存在標(biāo)簽文本文件中的邊界框的坐標(biāo)**必須被歸一化(從0到1)。**這非常重要。另外,如果圖像有多個標(biāo)注,在文本文件中,每個標(biāo)注(預(yù)測+邊框)將在單獨的行上。
在此之后,你需要一個配置文件,其中包含標(biāo)簽的名稱、類的數(shù)量以及訓(xùn)練和驗證的路徑。
importyaml classes=[‘Aorticenlargement’, ‘Atelectasis’, ‘Calcification’, ‘Cardiomegaly’, ‘Consolidation’, ‘ILD’, ‘Infiltration’, ‘LungOpacity’, ‘Nodule/Mass’, ‘Otherlesion’, ‘Pleuraleffusion’, ‘Pleuralthickening’, ‘Pneumothorax’, ‘Pulmonaryfibrosis’] data=dict( train=‘../vinbigdata/images/train’,#trainingimagespath val=‘../vinbigdata/images/val’,#validationimagespath nc=14,#numberofclasses names=classes ) withopen(‘./yolov5/vinbigdata.yaml’,‘w’)asoutfile: yaml.dump(data,outfile,default_flow_style=False)
現(xiàn)在,你需要做的就是運行這個命令:
pythontrain.py—img640—batch16—epochs30—data./vinbigdata.yaml—cfgmodels/yolov5x.yaml—weightsyolov5x.pt
從經(jīng)驗中需要注意的事情:
好了,現(xiàn)在我們已經(jīng)瀏覽了基本知識,讓我們來看看重要的東西:
別忘了歸一化坐標(biāo)。
如果你的初始性能比預(yù)期的差得多,那么最可能的原因(我在許多其他參賽者身上看到過這種情況)是你在預(yù)處理方面做錯了什么。這看起來很瑣碎,但有很多細(xì)節(jié)你必須注意,特別是如果這是你的第一次。
YoloV5有多種型號(yolov5s、yolov5m、yolov5l、yolov5x),不要只選擇最大的一個,因為它可能會過擬合。從一個基線開始,比如中等大小的,然后試著改善它。
雖然我是在512尺寸的圖像上訓(xùn)練的,但我發(fā)現(xiàn)用640來infer可以提高性能。
不要忘記加載預(yù)訓(xùn)練的權(quán)重(-weights標(biāo)志)。遷移學(xué)習(xí)將大大提高你的性能,并將為你節(jié)省大量的訓(xùn)練時間(在我的例子中,大約50個epoch,每個epoch大約需要20分鐘!)
Yolov5x需要大量的內(nèi)存,當(dāng)訓(xùn)練尺寸為512,批大小為4時,它需要大約14GB的GPU內(nèi)存(大多數(shù)GPU大約8GB內(nèi)存)。
YoloV5已經(jīng)使用了數(shù)據(jù)增強,你可以選擇喜歡或不喜歡的增強,你所需要做的就是使用yolov5/data/hyp.scratch.yml文件去調(diào)整。
默認(rèn)的yolov5訓(xùn)練腳本使用weights and biases,說實話,這非常令人印象深刻,它在模型訓(xùn)練時保存所有度量。但是,如果你想關(guān)閉它,只需在訓(xùn)練腳本標(biāo)記中添加WANDB_MODE= " dryrun "即可。
我希望早就發(fā)現(xiàn)的一件事是,YoloV5將大量有用的指標(biāo)保存到目錄YoloV5 /runs/train/exp/中。訓(xùn)練之后,你可以找到“confusion_matrix.png”和“results.png”,其中的result .png應(yīng)該是這樣的:
使用WBF預(yù)處理
好了,現(xiàn)在你已經(jīng)調(diào)整了超參數(shù),升級了你的模型,測試了多種圖像大小和交叉驗證?,F(xiàn)在是介紹一些提高性能的技巧的時候了。
加權(quán)框融合是一種在訓(xùn)練前(清理數(shù)據(jù)集)或訓(xùn)練后(使預(yù)測更準(zhǔn)確)動態(tài)融合框的方法。如果你想知道更多,你可以在這里查看我的文章:
WBF:優(yōu)化目標(biāo)檢測,融合過濾預(yù)測框 (qq.com)
要使用它對數(shù)據(jù)集進(jìn)行預(yù)處理,這將大多數(shù)參賽者的性能提高了大約10-20%,你可以這樣使用:
fromensemble_boxesimport* forimage_idintqdm(df['image_id'],leave=False): image_df=df[df['image_id']==image_id].reset_index(drop=True) h,w=image_df.loc[0,['height','width']].values boxes=image_df[['x_min','y_min','x_max','y_max']].values.tolist() #Normalisealltheboundingboxes(bydividingthembysize-1 boxes=[[j/(size-1)forjini]foriinboxes] scores=[1.0]*len(boxes)#setallofthescoresto1sinceweonlyhave1modelhere labels=[float(i)foriinimage_df['class_id'].values] boxes,scores,labels=weighted_boxes_fusion([boxes],[scores],[labels],weights=None,iou_thr=iou_thr, skip_box_thr=skip_box_thr) list_image.extend([image_id]*len(boxes)) list_h.extend([h]*len(boxes)) list_w.extend([w]*len(boxes)) list_boxes.extend(boxes) list_cls.extend(labels.tolist()) #bringtheboundingboxesbacktotheiroriginalsize(bymultiplyingbysize-1)list_boxes=[[int(j*(size-1))forjini]foriinlist_boxes] new_df['image_id']=list_image new_df['class_id']=list_cls new_df['h']=list_h new_df['w']=list_w #Unpackthecoordinatesfromtheboundingboxes new_df['x_min'],new_df['y_min'], new_df['x_max'],new_df['y_max']=np.transpose(list_boxes)
這意味著要在將邊框坐標(biāo)保存到標(biāo)注文件之前完成。你還可以嘗試在用YoloV5以同樣的方式預(yù)測邊界框之后使用它。
首先,在訓(xùn)練YoloV5之后,運行:
!pythondetect.py—weights/runs/train/exp/weights —img640 —conf0.005 —iou0.45 —source$test_dir —save-txt—save-conf—exist-ok
然后提取框、分?jǐn)?shù)和標(biāo)簽:
runs/detect/exp/labels
然后傳遞到:
boxes,scores,labels=weighted_boxes_fusion([boxes],[scores],[labels],weights=None,iou_thr=iou_thr, skip_box_thr=skip_box_thr)
最后的思考
我希望你已經(jīng)學(xué)到了一些關(guān)于擴展你的基線YoloV5的知識,我認(rèn)為最重要的事情總是要考慮的是遷移學(xué)習(xí),圖像增強,模型復(fù)雜性,預(yù)處理和后處理技術(shù)。這些是你可以輕松控制和使用YoloV5來提高性能的大部分方面。
責(zé)任編輯:lq
-
圖像分類
+關(guān)注
關(guān)注
0文章
89瀏覽量
11898 -
目標(biāo)檢測
+關(guān)注
關(guān)注
0文章
201瀏覽量
15578 -
遷移學(xué)習(xí)
+關(guān)注
關(guān)注
0文章
74瀏覽量
5554
原文標(biāo)題:高級YoloV5指南,使用WBF來提升目標(biāo)檢測性能
文章出處:【微信號:vision263com,微信公眾號:新機器視覺】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論