Keras-yolov3訓練

本教程爲keras-yolov3版本的訓練及測試全過程實現,爲保證對新手的友好性,不會過多解釋原理,主要是讓新手能對全過程有個比較清楚的概念和認識,方便訓練自己的數據。
本教程一共有三個部分:一.數據集準備及生成 二.訓練所需知識 三.測試及相關性能測試可視化

一.數據集準備及生成:
1.先來熟悉文件結構

font文件夾下是保存keras-yolov3可能會調用到的字體及顏色,在測試部分有用,方便在圖片上顯示相應文字標籤

logs文件夾是保存模型權重的,在訓練時也會保存tensorflow下的tensorboard可視化圖,可供查看訓練曲線

model_data文件夾下保存有coco_classes.txt,tiny_yolo_anchors.txt,voc_classes.txt,yolo.h5,yolo_anchors.txt,yolo-tiny.h5這6個文件,其中必須需要的是後5個。因爲在本次訓練中,全程按照VOC2007數據集格式來,所以coco_classes.txt文件中保存的coco數據集類別數據可以刪除不要,而後5個分別是yolo和tiny-yolo的anchors(錨點)大小和其在原版darknet下載訓練並轉換成keras模型的預訓練權重,這些在訓練過程中都要用到。

results文件夾是保存測試部分中對測試集圖片進行測試的結果,在測試分析中需要用到

VOCdevkit文件夾是所有數據存放的文件夾,其下文件夾目錄爲


進入VOC2007文件夾可看到


這裏Annotations文件夾保存的是所有圖片的標註框xml格式的數據。ImageSets文件夾下還有

在這裏插入圖片描述三個子文件夾,其中只有Main文件夾有用,裏面存放着訓練需要調用的圖片名稱,

在這裏插入圖片描述

這裏放着的是訓練集和測試集的圖片名稱,方便訓練時的調用。

JPEGImages文件夾下放着所有的圖片文件,可以是JPG或者PNG格式的圖片。
SegmentationClass和SegmentationObject是作爲語義分割中用的,這裏keras-yolov3是目標檢測,所以可以刪去不要。

訓練驗證測試集生成.py 文件是根據已有的xml(圖片)數據生成Main文件夾下的test.txt和train.txt文件的腳本。
新建文本文檔.py 文件是修改保存Annotations文件夾下的xml文件路徑的腳本,如果路徑都是對了,可以不用管這個腳本,如果不對,可以根據自己的文件所在目錄進行更改。

回到最開始的目錄,yolo3文件夾下保存的是keras-yolov3的模型源碼。

2007_train.txt和2007_test.txt是在標註完數據後調用voc_annotation.py文件生成的訓練數據和測試數據文件的集合,裏面存放着圖片路徑和目標框信息及類別信息。

剩下的.py文件中最重要的是convert.py,kmeans.py,train.py,voc_annotation.py,yolo.py,yolo_detect.py,yolov3.cfg,yolov3-tiny.cfg這幾個文件,其作用分別是:
convert.py 將darknet下訓練的權重轉化爲keras權重使用
kmeans.py 可以根據你自己的xml數據生成新的anchors(錨點),如果自己的數據集數據太特殊,目標太大或者太小導致使用原版效果不好,可以使用這個文件修改anchors,以達到檢測更好的效果
train.py 是訓練模型並保存權重的文件
voc_annotation.py 是根據已有數據集生成2007_train.txt和2007_test.txt這兩個訓練時真正調用的文件
yolo.py 定義了yolo模型類,並提供了一些方法,可以方便調用yolo功能進行測試
yolo_detect.py 可以測試圖片、視頻及實時攝像頭,直接生成結果
yolov3.cfg和yolov3-tiny.cfg是模型的config文件,裏面定義了模型的結構,一般不用改變,在訓練時會有一點地方需要改動

2.文件夾結構及作用講完後,可以開始準備數據了。先限定是自己的數據集,那麼只有源視頻數據或者圖片,沒有任何標註,那麼要做的第一件事是將視頻轉化爲圖片後存入VOCdevkit/VOC2007/JPEGImages文件目錄下,然後使用已經安裝好的labelImg對該目錄下圖片進行標註,並將生成的xml文件存入VOCdevkit/VOC2007/Annotations文件目錄下。這兩步做完後,運行 python 訓練驗證測試集生成.py 命令會在同目錄下的ImageSets/Main文件下生成train.txt和test.txt,其train和test之間的比例可以通過改變訓練驗證測試集生成.py腳本中的test_percent = 0.1和train_percent = 0.9這兩個數字進行改變。
之後返回根目錄,運行 python voc_annotation.py 命令生成訓練模型真正需要的2007_train.txt和2007_test.txt文件。至此,數據集的準備已經全部完成。

二.訓練所需知識 :
準備好數據集後當然就是開始訓練,在訓練前有兩個文件中的內容需要修改
–model_data/voc_classes.txt文件和yolov3.cfg文件,在voc_classes.txt中你只需要將根據你數據集的種類和標註時的標籤對上,寫下英文名字即可

在這裏插入圖片描述

這裏只有房子這一類,那麼房子在標註時label設爲0,在這裏放第一個,如果有多類,只需要按照標註時的label數字從小到大寫好就可以了;
yolov3.cfg中需要改的地方一共有三處:先進入文件,搜索 yolo 變會有三處地方顯示出來,這三處都需要根據自己數據進行修改。如下圖:

在這裏插入圖片描述

這是其中一處,這裏我標註了三個地方需要改變,帶有###change的就是了,filters根據公式3*(5+數據集類別數目)可以修改,這裏只有一類那麼修改爲filters=18就可以(3*(5+1)=18);classes=2修改classes=1,因爲只有一類;random=0代表了多尺度訓練不開啓,不開啓對顯存的要求會更低,這樣顯存不夠的顯卡也可以訓練,如果random=1那麼多尺度訓練開啓,在訓練中圖片會隨機增強放大等等,對顯存要求更高,這裏設爲0即可。
剩下兩處也跟這裏一樣進行修改即可。

修改完這兩個文件後,就可以進行train.py文件準備開始訓練了,下面講解一下train.py文件中的一些參數,方便自己訓練修改:

在這裏插入圖片描述上圖中的annotation_path,log_dir,classes_path,anchors_path分別代表了訓練圖片數據的路徑,模型存放路徑,數據集種類路徑,模型anchors數據路徑,這些自己都是可以修改的,這裏我們因爲前面的數據生成一直按照VOC2007格式來,所以這裏可以不用變。

上圖代表訓練圖片輸入的寬高大小,其數值必須是32的倍數,一般設置爲(320

,320),(416,416),(608,608)這個根據你顯存的大小和數據目標框大小進行改變,一般情況下(416,416)即可,這代表訓練時會把圖片都變成這個大小再送入網絡中。

在這裏插入圖片描述

這裏選擇是使用yolov3的模型還是tiny-yolov3模型,tiny相對小速度快,不過精度降低。

這裏進行數據的訓練集和驗證集劃分,比例9:1,可以自行更改。

在這裏插入圖片描述

這裏加載預訓練模型進行預熱,其作用在於使用預訓練模型權重,只改變後兩層的權重,前面特徵提取的權重都沒變,爲後面不凍結模型-全部層訓練打下了基礎,方便其loss的降低,這裏batch_size和epochs都可以更改,不過一般修改batch_size就夠了,顯存大的可以改大,預熱訓練完成後模型權重會保存到’logs/000/trained_weights_stage_1.h5’這裏。

在這裏插入圖片描述

這裏開啓了所有層,都進行訓練,輪數更多,以便訓練到比較好的效果,讓loss收斂。
注意:在keras-yolov3中因爲模型構建時使用了l2正則化的措施,所以最終模型的loss都不會降到特別低,一般keras-yolov3loss降到10左右效果便可以了。
訓練到結束即可,訓練過程就此結束。

三.測試及相關性能測試可視化:
對單張圖片,視頻及攝像頭測試可以使用 yolo_detect.py , 只要輸入相應的參數即可,比如輸入 python yolo_detect.py --image 後就可以對單張圖片進行測試等等。這裏要注意其調用的都是 yolo.py 中的Yolo類

在這裏插入圖片描述

這些都是可以根據你自己實際需求改的,比如model_path就是你想測試的模型權重路徑,anchors_path和classes_path也是同理,score代表一個閾值,只有置信度高於此值的目標纔會被框出來,iou也是同理,model_image_size需要跟你訓練時的input_shape一致,gpu_num代表你是否加載多GPU進行測試。
VOC測試集信息生成.py 文件使用了yolo.py 中的Yolo類進行測試集圖片的測試,並將生成的結果保存下來,可以作爲 pr曲線繪製和map計算的依據。
VOC測試集PR和MAP結果.py 文件調用了 voc_eval_py3.py 文件中的方法計算pr曲線和MAP,並將結果保存下來。

四. 結語:
這篇教程詳細闡述了keras-yolov3下的訓練和測試全過程,對關鍵地方進行了解釋和說明,讀者可以自行更改。關於yolov3 的原理可以自行去查閱資料,這裏不作過多解釋。

心得:

在keras-yolov3下,.cfg文件可以不用,在darknet下才有用,只是作爲學習其結構的參考,所以我改了backbone後,將darknet_body改爲mobilenet_body,一樣可以正常訓練和運行,只要保持結構一致即可。
在keras-yolov3下,主要修改的參數還是yolo_anchors.txt和train.py裏create_model的ignoresh參數,還有input_shape,這個是決定你顯存的,所以,由此也可以看出,keras-yolov3的效果比darknet原版差一些也是自然的,因爲很多設置都是沒法調的,能改的地方不多。
仿照原版的結構來理解即可,參讀了一下源碼,還是基本一致的,所以效果也還是可以的。進一步改進除了我改了的backbon外,估計就是改進結構了,那這個模型就得重新寫了。大概就是這樣
————————————————

1. 下載YOLOv3工程項目
git clone https://github.com/pjreddie/darknet  
cd darknet  
1
2
2. 修改Makefile配置,使用GPU訓練,修改如下:
GPU=1 #如果使用GPU設置爲1,CPU設置爲0
CUDNN=1  #如果使用CUDNN設置爲1,否則爲0
OPENCV=0 #如果調用攝像頭,還需要設置OPENCV爲1,否則爲0
OPENMP=0  #如果使用OPENMP設置爲1,否則爲0
DEBUG=0  #如果使用DEBUG設置爲1,否則爲0

CC=gcc
NVCC=/home/user/cuda-9.0/bin/nvcc   #NVCC=nvcc 修改爲自己的路徑
AR=ar
ARFLAGS=rcs
OPTS=-Ofast
LDFLAGS= -lm -pthread 
COMMON= -Iinclude/ -Isrc/
CFLAGS=-Wall -Wno-unused-result -Wno-unknown-pragmas -Wfatal-errors -fPIC
...
ifeq ($(GPU), 1) 
COMMON+= -DGPU -I/home/hebao/cuda-9.0/include/  #修改爲自己的路徑
CFLAGS+= -DGPU
LDFLAGS+= -L/home/hebao/cuda-9.0/lib64 -lcuda -lcudart -lcublas -lcurand  #修改爲自己的路徑
endif

保存完成後,在此路徑下執行make,如果出現如下錯誤:

Loadingweights from yolo.weights...Done!
CUDA Error:invalid device function
darknet: ./src/cuda.c:21: check_error: Assertion `0' failed.
Aborted (core dumped)

這是因爲配置文件Makefile中配置的GPU架構和本機GPU型號不一致導致的。更改前默認配置如下(不同版本可能有變):

ARCH= -gencode arch=compute_30,code=sm_30 \
      -gencode arch=compute_35,code=sm_35 \
      -gencode arch=compute_50,code=[sm_50,compute_50] \
      -gencode arch=compute_52,code=[sm_52,compute_52]
#      -gencode arch=compute_20,code=[sm_20,sm_21] \ This one is deprecated?
# This is what I use, uncomment if you know your arch and want to specify
# ARCH= -gencode arch=compute_52,code=compute_52

CUDA官方說明文檔:http://docs.nvidia.com/cuda/cuda-compiler-driver-nvcc/index.html#virtual-architecture-feature-list

然後重新編譯即可:


3. 準備訓練數據集
按下列文件夾結構,將訓練數據集放到各個文件夾下面,生成4個訓練、測試和驗證txt文件列表
VOCdevkit
—VOC2007
——Annotations
——ImageSets
———Layout
———Main
———Segmentation
——JPEGImages
Annotations中是所有的xml文件
JPEGImages中是所有的訓練圖片
Main中是4個txt文件,其中test.txt是測試集,train.txt是訓練集,val.txt是驗證集,trainval.txt是訓練和驗證集。

3. 生成2007_train.txt和2007_val.txt文件
下載voc_label.py文件,將文件下載到VOCdevkit同級的路徑下,生成訓練和驗證的文件列表
wget https://pjreddie.com/media/files/voc_label.py

修改sets爲訓練樣本集的名稱
sets=[('2007', 'train')]
修改classes爲訓練樣本集的類標籤
classes=[str(i) for i in range(10)]
1
2
3
4
運行python voc_label.py,生成2007_train.txt訓練文件列表。

4.下載Imagenet上預先訓練的權重
wget https://pjreddie.com/media/files/darknet53.conv.74 
1
5. 修改cfg/voc.data
classes= 10  #classes爲訓練樣本集的類別總數
train  = /home/user/darknet/2007_train.txt  #train的路徑爲訓練樣本集所在的路徑
valid  = /home/user/darknet/2007_val.txt  #valid的路徑爲驗證樣本集所在的路徑
names = data/voc.names  #names的路徑爲data/voc.names文件所在的路徑
backup = backup

6. 在darknet文件夾下面新建文件夾backup
7. 修改data/voc.name爲樣本集的標籤名

8. 修改cfg/yolov3-voc.cfg
關於cfg修改,以10類目標檢測爲例,主要有以下幾處調整(藍色標出):

[net]
# Testing            ### 測試模式                                          
# batch=1
# subdivisions=1
# Training           ### 訓練模式,每次前向的圖片數目 = batch/subdivisions 
batch=64
subdivisions=16
width=416            ### 網絡的輸入寬、高、通道數
height=416
channels=3
momentum=0.9         ### 動量 
decay=0.0005         ### 權重衰減
angle=0
saturation = 1.5     ### 飽和度
exposure = 1.5       ### 曝光度 
hue=.1               ### 色調
learning_rate=0.001  ### 學習率 
burn_in=1000         ### 學習率控制的參數
max_batches = 50200  ### 迭代次數                                          
policy=steps         ### 學習率策略 
steps=40000,45000    ### 學習率變動步長 
scales=.1,.1         ### 學習率變動因子  

[convolutional]
batch_normalize=1    ### BN
filters=32           ### 卷積核數目
size=3               ### 卷積核尺寸
stride=1             ### 卷積核步長
pad=1                ### pad
activation=leaky     ### 激活函數

......

[convolutional]
size=1
stride=1
pad=1
filters=45  #3*(10+4+1)
activation=linear

[yolo]
mask = 6,7,8
anchors = 10,13,  16,30,  33,23,  30,61,  62,45,  59,119,  116,90,  156,198,  373,326
classes=10  #類別
num=9
jitter=.3
ignore_thresh = .5
truth_thresh = 1
random=0  #1,如果顯存很小,將random設置爲0,關閉多尺度訓練;
......

[convolutional]
size=1
stride=1
pad=1
filters=45  #3*(10+4+1)
activation=linear

[yolo]
mask = 3,4,5
anchors = 10,13,  16,30,  33,23,  30,61,  62,45,  59,119,  116,90,  156,198,  373,326
classes=10  #類別
num=9
jitter=.3
ignore_thresh = .5
truth_thresh = 1
random=0  #1,如果顯存很小,將random設置爲0,關閉多尺度訓練;
......

[convolutional]
size=1
stride=1
pad=1
filters=45  #3*(10+4+1)
activation=linear

[yolo]
mask = 0,1,2
anchors = 10,13,  16,30,  33,23,  30,61,  62,45,  59,119,  116,90,  156,198,  373,326
classes=10  #類別
num=9
jitter=.3  # 數據擴充的抖動操作
ignore_thresh = .5  #文章中的閾值1
truth_thresh = 1  #文章中的閾值2
random=0  #1,如果顯存很小,將random設置爲0,關閉多尺度訓練;

9. 開始訓練
./darknet detector train cfg/voc.data cfg/yolov3-voc.cfg darknet53.conv.74 -gpus 0,1
1
10. 識別
將訓練得到的weights文件拷貝到darknet/weights文件夾下面

./darknet detect cfg/yolov3-voc.cfg weights/yolov3.weights data/dog.jpg
————————————————
版權聲明:本文爲CSDN博主「john_bh」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/john_bh/article/details/80625220

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章