【目標檢測七】FPN-從原理到模型的訓練與測試

             FPN:原理 => 模型搭建 => 訓練 => 測試

目錄

             FPN:原理+模型搭建+訓練自己的數據+測試

原理簡介

【FPN】

【創新點】

【動機】

【有效性分析】

模型搭建

1.環境搭建

2.下載源代碼

3.跑一下Demo測試一下模型

訓練自己的數據

1.數據準備

3.跑起來

測試自己的數據

1.參數設置

2.驗證測試


FPN論文名:feature pyramid networks for object detection

論文下載https://arxiv.org/abs/1612.03144

作者Tsung-Yi LinPiotr DollárRoss GirshickKaiming He, Bharath HariharanSerge Belongie

代碼https://github.com/yangxue0827/FPN_Tensorflow

-------------------------------

原理簡介

-------------------------------

【FPN】

特徵金字塔網絡,是衆多卷積神經網絡結構中的一種。

【創新點】

特徵的構建和對特徵的應用呈現出一種金字塔狀的多尺度方式。這裏的多尺度有兩個層次,一個是特徵的多尺度:構建了不同分辨率的融合特徵;另一個是多尺度是應用的多尺度,在多個不同尺度的特徵上分別做分類和迴歸。

【動機】

1.針對深度網絡中語義不能兼顧的問題,設計一種能夠兼顧底層和高層特徵的卷積神經網絡結構

2.附帶針對:小目標。

【有效性分析】

1.特徵融合是一個被證明有效的,通過增加計算量來提高模型性能的方式,FPN提供的,是一種更充分的特徵融合,因爲每一種分辨率的特徵,都被用於融合,而融合結果也不是侷限於單一的一個特徵,而是同樣融合出多種分辨率的特徵,並且融合的特徵之間還有遞進關係,更後面的特徵融合將會用到前面的融合特徵。在這麼一個不同層之間構建了豐富的信息交互,保證了從頭到尾有效信息的傳播。

2.關於小目標的檢測,是其主打賣點。有用的原因主要有三個,第一個是更充分的利用了底層特徵,而小目標正是因爲小,所以在底層的信息纔是最多的,所以對於小目標的特徵是被優化了的。第二,就是在不同尺度的特徵上都做預測,本質就是加大了搜索粒度,因爲每個尺度的Feature上都會產生anchor,那麼三個尺度的特徵上都做預測,本質上,anchor boxes會更多更充分更準確的包含到小目標,也就是能更好的將小目標檢索出來。第三,是原因1和原因2的共同作用,特徵優化了,搜索更細了,這纔是效果直接提升的必要因素,也就是我能框出更多的框,並且小框的特徵還更有效。

3.模型結構:這些其他博客都很多了,不必贅述。

4.關於FPNFaster R-CNN等模型的關係。其實FPN不是一個單獨的網絡,其提出的是一種主幹網絡以及對應該主幹網絡的一種檢測方式。也就相當於把Faster R-CNN中的Backbone從ResNet-101的連接結構變成FPN結構,然後將Faster R-CNN的RPN輸入從原來的最後一個特徵層變爲多個特徵層(不同尺度的融合特徵),也可以理解爲將RPN複製多次。所以大家看源代碼的時候,就當成Faster R-CNN的一種改進看就可以了。其他部分都一樣的。

-------------------------------

模型搭建

-------------------------------

1.環境搭建

ubuntu + python2 + tensorflow1.2 + cv2 + cuda8.0 (+ GeForce GTX 1080)

作者將自己的環境用Docker打包了一份,So,
You can also use docker environment, command:

docker pull yangxue2docker/tensorflow3_gpu_cv2_sshd:v1.0

2.下載源代碼

git clone https://github.com/yangxue0827/FPN_Tensorflow.git   

3.跑一下Demo測試一下模型

1、解壓基於res101訓練好的demo模型:

  文件在 FPN根目錄/output/res101_trained_weights/(一個飛機檢測的模型)


2、在測試圖像文件夾裏面丟一些包含目標(飛機)的圖片。本身就有幾張,故可不放。

      文件夾爲:FPN根目錄/tools/inference_image


3、修改模型的絕對路徑。因爲內部的調用都需要基於一個路徑,這裏作者集成到配置文件cfgs.py中了。在裏面直接改就行,然後其他的路徑就都會根據這個來。

在這裏面修改:FPN根目錄/libs/configs/cfgs.py 
# 找到這一句,將後面的路徑改爲自己FPN的文件夾位置
ROOT_PATH = os.path.abspath(r'C:\Users\yangxue\Documents\GitHub\FPN_Tensorflow')

4、運行代碼測試:

這裏作者提供兩種代碼,一種是用於跑小圖片的(作者所用數據集中的.jpg爲小分辨率圖像),一種是用於跑大圖的,.tif結尾的是分辨率大的大圖。

###跑小圖

cd FPN根目錄/tools
python inference.py   

(注:大圖小圖都可以跑,大圖就用最小邊壓縮了一下)

###跑大圖

cd FPN根目錄/tools
python demo.py --src_folder=.\demo_src --des_folder=.\demo_des 


(注:這個demo只處理.tif結尾的大圖,src_folder和des_folder後面修改爲測試圖片和保存測試結果的文件夾位置。)   

一般就用第一個就行了。後面那個也就相當換了一種方式處理格式問題,然後還是用最小邊縮小大圖。

【測試結果】

到此,模型搭建完成,測試通過。

-------------------------------

訓練自己的數據

-------------------------------

1.數據準備

將自己的PASCAL_VOC數據集拆分爲訓練集、測試集合。適用/data/io/divide_data.py

具體的拆分比例,調節divide_data.py中的divide_rate = 0.8。

python /data/io/divide_data.py

在根目錄下,將會生成兩個文件夾:VOCdevkit_train 和 VOCdevkit_test

下一步,需要分別將訓練和測試數據轉換成 TFrecord 格式。該格式是TensorFlow的高效存儲格式,連續的內存二進制存儲能夠有效的加快數據的讀取和寫入。而像原始文件夾那樣每個數據獨立存儲。

轉換的代碼爲 /data/io/convert_data_to_tfrecord.py

python convert_data_to_tfrecord.py --VOC_dir='***/VOCdevkit/VOCdevkit_train/' --save_name='train' --img_format='.jpg' --dataset='ship'

在使用的時候,訓練和測試數據分別使用。.py後面的參數需要根據自己的路徑和數據集進行修改。參數說明如下:

# 上一步訓練、測試數據分離後的文件夾路徑。
--VOC_dir='你的FPN路徑/VOCdevkit/VOCdevkit_train/' 
#tfrecord名字。訓練數據用'train' ,測試數據用'test'
--save_name='train' 
#你的圖片格式。有Png\tif\jpeg
--img_format='.jpg' 
#你的數據集名字。這個需要在/libs/label_name_dict/label_dict.py中添加自己的數據集
--dataset='mydataset'

上面的參數前三個都Ok,第四個需要添加自己數據集的類別字典,所以你無法直接運行上面的代碼。需要修改以下:

在/libs/label_name_dict/label_dict.py中添加自己的數據集標籤類別。具體如下:

# -*- coding: utf-8 -*-
from __future__ import division, print_function, absolute_import

from libs.configs import cfgs

if cfgs.DATASET_NAME == 'ship':
    NAME_LABEL_MAP = {
        'back_ground': 0,
        "ship": 1
    }
##########################
###插入以下:--dataset='mydataset'中的名字一致就是調用到這個字典的。
別人我爲什麼需要自己數據集訓練數據類別的字典- -
因爲字典不同訓練的模型後面的softmax層大小不一樣。2類就2個。
4類的話softmax就有4個節點。這個需要訓練師自己確認。
(而不是因爲無法從你的dataset自動的統計你的類別名字及其數量。)
##########################
elif cfgs.DATASET_NAME == 'mydataset':#這個名字就是你數據集類別字典的名字了。
    NAME_LABEL_MAP = {
        'back_ground': 0,
        "你的類1": 1
        "你的類2": 2
        "你的類3": 3
......
    }

##########################
###實際上和下面的格式都一樣。
##########################
elif cfgs.DATASET_NAME == 'SSDD':
    NAME_LABEL_MAP = {
        'back_ground': 0,
        "ship": 1
    }
elif cfgs.DATASET_NAME == 'airplane':
    NAME_LABEL_MAP = {
        'back_ground': 0,
        "airplane": 1
    }
elif cfgs.DATASET_NAME == 'nwpu':
    NAME_LABEL_MAP = {
        'back_ground': 0,
        'airplane': 1,
        'ship': 2,
        'storage tank': 3,
        'baseball diamond': 4,
        'tennis court': 5,
        'basketball court': 6,
        'ground track field': 7,
        'harbor': 8,
        'bridge': 9,
        'vehicle': 10,
    }

....
.....
......
.......

然後就可以運行convert_data_to_tfrecord.py了。別忘了填上四個參數。

python convert_data_to_tfrecord.py --VOC_dir='***/VOCdevkit/VOCdevkit_train/' --save_name='train' --img_format='.jpg' --dataset='ship'

運行結果就是得到訓練、測試數據的tfrecord格式數據,在 /data/tfrecords/ 裏面。你可以自己檢查一下。

2.參數設置

數據準備好了,那麼訓練就要調參和調一些路徑啦。打開/libs/configs/cfgs.py,按我的註釋來。

對應裏面的model,應先下載好預訓練模型,放在 /data/pretrained_weights/ 中。

預訓練模型的下載地址:

 Res101: http://download.tensorflow.org/models/resnet_v1_101_2016_08_28.tar.gz

Res50: http://download.tensorflow.org/models/resnet_v1_50_2016_08_28.tar.gz

# -*- coding: utf-8 -*-
from __future__ import division, print_function, absolute_import
import os

#####
初始化設置
#####

# 你的FPN目錄地址
ROOT_PATH = os.path.abspath(r'C:\Users\yangxue\Documents\GitHub\FPN_Tensorflow')

# pretrain weights path
#測試結果保存路徑,上面我們已經測試過了 不用改。
TEST_SAVE_PATH = ROOT_PATH + '/tools/test_result'
INFERENCE_IMAGE_PATH = ROOT_PATH + '/tools/inference_image'
INFERENCE_SAVE_PATH = ROOT_PATH + '/tools/inference_result'
#使用的model。
NET_NAME = 'resnet_v1_101'
#你的本次訓練項目名字。每當重新訓練一次,最好在後面加一個01\02區別。名字重複了就會訓亂。按這個名字會有output裏面生成對應名字的文件夾,保存訓練的Net
VERSION = 'v1_mydataset'
#你的類別數,是幾類就寫幾。
CLASS_NUM = 1




BASE_ANCHOR_SIZE_LIST = [15, 25, 40, 60, 80]
LEVEL = ['P2', 'P3', 'P4', 'P5', "P6"]
STRIDE = [4, 8, 16, 32, 64]
ANCHOR_SCALES = [1.]
ANCHOR_RATIOS = [1, 0.5, 2, 1 / 3., 3., 1.5, 1 / 1.5]
SCALE_FACTORS = [10., 10., 5., 5.]
OUTPUT_STRIDE = 16
SHORT_SIDE_LEN = 600
####改成自己數據集字典的名字
DATASET_NAME = 'mydataset'
####
BATCH_SIZE = 1
WEIGHT_DECAY = {'resnet_v1_50': 0.0001, 'resnet_v1_101': 0.0001}
EPSILON = 1e-5
MOMENTUM = 0.9
MAX_ITERATION = 50000
GPU_GROUP = "1"
LR = 0.001

# rpn
SHARE_HEAD = True
RPN_NMS_IOU_THRESHOLD = 0.5
MAX_PROPOSAL_NUM = 2000
RPN_IOU_POSITIVE_THRESHOLD = 0.5
RPN_IOU_NEGATIVE_THRESHOLD = 0.2
RPN_MINIBATCH_SIZE = 512
RPN_POSITIVE_RATE = 0.5
IS_FILTER_OUTSIDE_BOXES = True
RPN_TOP_K_NMS = 12000

# fast rcnn
ROI_SIZE = 14
ROI_POOL_KERNEL_SIZE = 2
USE_DROPOUT = False
KEEP_PROB = 0.5
FAST_RCNN_NMS_IOU_THRESHOLD = 0.2
FAST_RCNN_NMS_MAX_BOXES_PER_CLASS = 100
FINAL_SCORE_THRESHOLD = 0.5
FAST_RCNN_IOU_POSITIVE_THRESHOLD = 0.45
FAST_RCNN_MINIBATCH_SIZE = 256
FAST_RCNN_POSITIVE_RATE = 0.5

 

3.跑起來

在根目錄下打開終端。運行以下:

python /tools/train.py 

等着訓練完成吧。

-------------------------------

測試自己的數據

-------------------------------

1.參數設置

測試實際上包括指標驗證和保存測試結果。如果只是像將測試集跑一邊然後將結果保存下來,就用/tools/test.py

如果是想驗證,就用/tools/eval.py

在test.py或eval.py裏面有對應的測試參數可以改,比如正樣本閾值等。

2.驗證測試

運行代碼。

python /tools/test.py
或者
python /tools/eval.py

運行test.py的話你會在./tools/test_result裏獲得測試集的圖片檢測結果。

運行eval.py則得到 AP、Recall 和mAP。

以上。

------------------------

作者優化的FPN版本:https://github.com/DetectionTeamUCAS/FPN_Tensorflow

作者給出了一個優化版本。因爲原來的版本在訓練的過程中因爲summary的可視化原因,會終止訓練。

比如tensorboard顯示proposals圖像結果的時候,畫了超出圖像的框等。就會終止訓練。如果不想換模型,把對應的地方註釋掉就可以,一般大家可能也用不到tensorboard。另一個就是使用方面的優化。優化版的代碼用eval.py就可以直接獲取指標驗證結果以及測試結果,只需要調節一個參數。

以上是我使用時發現的主要兩點感受。

兩個使用方法大同,不贅述。

------------------------

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