超詳細教程:YOLO_V3訓練自己的資料
前言:最近剛好做一個專案需要做detection,選擇的演算法是yolo v3,因為它既有速度又有精度,還非常靈活,簡直是工業界良心。做專案免不了需要用到自己的資料集,所以得從頭一個腳印的來,走通了之後決定寫一個帖子,讓需要用的人少走歪路,節約時間。
官網上已經教我們如何跑起來yolo v3,因此大部分時間其實花在製作資料集上。總體來說,分為四個步驟,分別是:標註資料,利用voc製作自己的資料集,下載並編譯原始碼,區域性修改和大功告成(前兩步可以在方便操作的環境下(windows或linux)進行,後面幾步在linux環境進行)
一、標註資料
-
工具:
使用的標註工具是labelimg,其他標註工具也行,但是生成的標註label檔案要是xml。這裡給一個labelimg軟體的傳送門 -
資料集編號:
為了規劃自己的資料,減少出錯的可能性,最好自己先給自己的圖片編一個合理的序號,比如0001~0999。 -
標註資料:
利用軟體把自己的資料標註好。每一個圖片名對應的有一個相應名字的label.xml。
xml中的資料如下所示。這時候的path不用管他,在訓練的時候不會用到這裡的資料,這裡後面會說到。
二、利用voc製作自己的資料集
在目錄下新建VOC2007,並在VOC2007下新建Annotations,ImageSets和JPEGImages三個資料夾。在ImageSets下新建Main資料夾。檔案目錄如下所示:
將自己的資料集圖片拷貝到JPEGImages目錄下。將資料集label檔案拷貝到Annotations目錄下。在VOC2007下新建test.py資料夾,將下面程式碼拷貝進去執行,將生成四個檔案:train.txt,val.txt,test.txt和trainval.txt。
import os import random trainval_percent = 0.1 train_percent = 0.9 xmlfilepath = 'Annotations' txtsavepath = 'ImageSets\Main' total_xml = os.listdir(xmlfilepath) num = len(total_xml) list = range(num) tv = int(num * trainval_percent) tr = int(tv * train_percent) trainval = random.sample(list, tv) train = random.sample(trainval, tr) ftrainval = open('ImageSets/Main/trainval.txt', 'w') ftest = open('ImageSets/Main/test.txt', 'w') ftrain = open('ImageSets/Main/train.txt', 'w') fval = open('ImageSets/Main/val.txt', 'w') for i in list: name = total_xml[i][:-4] + '\n' if i in trainval: ftrainval.write(name) if i in train: ftest.write(name) else: fval.write(name) else: ftrain.write(name) ftrainval.close() ftrain.close() fval.close() ftest.close()
生成後的目錄結構如下所示:
做好這一步之後,自己的資料集基本做好了,接下來需要轉移陣地到程式碼環境中去。
三、下載並編譯原始碼
YOLOV3的主頁:https://pjreddie.com/darknet/yolo/
1、下載程式碼:
git clone https://github.com/pjreddie/darknet
2、編譯程式碼:
YOLOV3使用一個開源的神經網路框架Darknet53,使用C和CUDA,有CPU和GPU兩種模式。預設使用的是CPU模式,需要切換GPU模型的話,vim修改Makefile檔案。
cd darknet
vim Makefile #如果使用CPU模式。則不用修改Makefile檔案
將前面三行置1,其他不用動。
make
編譯成功後,可以先下載預訓練模型測試一下效果。
wget https://pjreddie.com/media/files/yolov3.weights
./darknet detect cfg/yolov3.cfg yolov3.weights data/dog.jpg
可以看到YOLO的detection圖。到這裡,YOLOV3已經走通了,是時候加入自己的資料了。
3、加入自己的資料集
在程式碼的darknet目錄下新建VOCdevkit資料夾,然後把剛才製作的VOC2007資料夾拷貝到該資料夾下。
有的讀者可能瞭解過YOLOV3的label,YOLOV3的label標註的一行五個數分別代表類別(從 0 開始編號), BoundingBox 中心 X 座標,中心 Y 座標,寬,高。這些座標都是 0~1 的相對座標。和我們剛才標註的label不同,因此我們需要下面的py檔案幫我們轉換label。
wget https://pjreddie.com/media/files/voc_label.py
這裡需要修改兩個地方,sets和classes,classes根據自己需要修改。
接下來執行該檔案,我們的目錄下會生成三個txt檔案2007_train.txt,2007_val.txt,2007_test.txt,VOCdevkit下的VOC2007也會多生成一個labels資料夾,下面是真正會使用到的label,點開看發現已經轉化成YOLOV3需要的格式了。這時候自己的資料集正式完成。
python voc_label.py
cat 2007_train.txt 2007_val.txt > train.txt
四、區域性修改
1、 修改cfg/voc.data
根據自己的路徑修改。
2、修改data/voc.names和coco.names
開啟對應的檔案都是原本資料集裡的類,改成自己的類就行。
3、修改引數檔案cfg/yolov3-voc.cfg
ctrl+f搜 yolo, 總共會搜出3個含有yolo的地方。
每個地方都必須要改2處, filters:3*(5+len(classes));
其中:classes: len(classes) = 1,這裡以單個類dog為例
filters = 18
classes = 1
可修改:random = 1:原來是1,視訊記憶體小改為0。(是否要多尺度輸出。)
引數檔案開頭的地方可以選訓練的batchsize,要注意!
五、大功告成
如果讀者按照步驟已經耐心的到這裡了,可以舒一口氣了,離成功只差一步了。
下載darknet53的預訓練模型。
wget https://pjreddie.com/media/files/darknet53.conv.74
開始訓練:
./darknet detector train cfg/voc.data cfg/yolov3-voc.cfg darknet53.conv.74
六、關於神經網路訓練的討論:
過擬合該怎麼繼續訓練?
看到書上寫道:有了BN之後,就不要正則化去防止過擬合了,比如dropout,L2正則化。實際上也試過確實沒什麼效果,有時候還會降低結果。這時候train上和valid上表現有差異該怎麼解決?是資料集本身就有的分佈差異導致的,還是可以通過其他手段解決,如減小模型。歡迎大家討論留言。