1. 程式人生 > >超詳細教程:YOLO_V3訓練自己的資料

超詳細教程:YOLO_V3訓練自己的資料

前言:最近剛好做一個專案需要做detection,選擇的演算法是yolo v3,因為它既有速度又有精度,還非常靈活,簡直是工業界良心。做專案免不了需要用到自己的資料集,所以得從頭一個腳印的來,走通了之後決定寫一個帖子,讓需要用的人少走歪路,節約時間。
官網上已經教我們如何跑起來yolo v3,因此大部分時間其實花在製作資料集上。總體來說,分為四個步驟,分別是:標註資料,利用voc製作自己的資料集,下載並編譯原始碼,區域性修改和大功告成(前兩步可以在方便操作的環境下(windows或linux)進行,後面幾步在linux環境進行)

一、標註資料

  1. 工具:
    使用的標註工具是labelimg,其他標註工具也行,但是生成的標註label檔案要是xml。這裡給一個labelimg軟體的傳送門

    https://pan.baidu.com/s/1tuIQmuyedRHP1WeGVVSx_Q 提取碼: ejgx 。

  2. 資料集編號:
    為了規劃自己的資料,減少出錯的可能性,最好自己先給自己的圖片編一個合理的序號,比如0001~0999。

  3. 標註資料:
    利用軟體把自己的資料標註好。每一個圖片名對應的有一個相應名字的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上表現有差異該怎麼解決?是資料集本身就有的分佈差異導致的,還是可以通過其他手段解決,如減小模型。歡迎大家討論留言。