前言:做目標檢測,選擇的算法是yolo v3,因爲它既有速度又有精度,還非常靈活,簡直是工業界良心。做項目免不了需要用到自己的數據集,所以得從頭一個腳印的來,走通了之後決定寫一個帖子,讓需要用的人少走歪路,節約時間。
官網上已經教我們如何跑起來yolo v3,因此大部分時間其實花在製作數據集上。總體來說,分爲四個步驟,分別是:標註數據,利用voc製作自己的數據集,下載並編譯源碼,局部修改和大功告成(前兩步可以在方便操作的環境下(windows或linux)進行,後面幾步在linux環境進行)
一、標註數據
-
工具:
使用的標註工具是labelimg,其他標註工具也行,但是生成的標註label文件要是xml。這裏給一個labelimg軟件的傳送門 https://pan.baidu.com/s/1tuIQmuyedRHP1WeGVVSx_Q 提取碼: ejgx 。 -
數據集編號:
爲了規劃自己的數據,減少出錯的可能性,最好自己先給自己的圖片編一個合理的序號,比如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
- 1
2、編譯代碼:
YOLOV3使用一個開源的神經網絡框架Darknet53,使用C和CUDA,有CPU和GPU兩種模式。默認使用的是CPU模式,需要切換GPU模型的話,vim修改Makefile文件。
cd darknet
vim Makefile #如果使用CPU模式。則不用修改Makefile文件
- 1
- 2
將前面三行置1,其他不用動。
make
- 1
編譯成功後,可以先下載預訓練模型測試一下效果。
wget https://pjreddie.com/media/files/yolov3.weights
./darknet detect cfg/yolov3.cfg yolov3.weights data/dog.jpg
- 1
- 2
可以看到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
- 1
這裏需要修改兩個地方,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
- 2
四、局部修改
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
- 1
開始訓練:
./darknet detector train cfg/voc.data cfg/yolov3-voc.cfg darknet53.conv.74
- 1
六、關於神經網絡訓練的討論:
過擬合該怎麼繼續訓練?
看到書上寫道:有了BN之後,就不要正則化去防止過擬合了,比如dropout,L2正則化。實際上也試過確實沒什麼效果,有時候還會降低結果。這時候train上和valid上表現有差異該怎麼解決?是數據集本身就有的分佈差異導致的,還是可以通過其他手段解決,如減小模型。歡迎大家討論留言。