tf-faster-rcnn的訓練流程及其如何訓練自己的數據集(一)

前言:

關於faster rcnn的訓練網絡,哪怕你一直很努力,死磕代碼。就會像這圖一樣智商不夠用啊,這邊看了那邊忘。所以希望大家能體系的學習faster rcnn。因爲走了很多彎路,總結一下自己的理解。本篇關於Faster rcnn 的訓練是基於tensorflow版本的,因爲最近一直在搞這個,也爲了鞏固一下知識點,在此寫個博客,也希望能幫助到大家。廢話不多說,我們直接開始。

第一點:首先要明白faster rcnn目錄下都有哪些文件夾,都有什麼用處。如下截圖:

文件夾:

data--------->存放的是用於訓練的數據集,一般我們用的都是voc2007的數據集,知道就行了,還有一個很重要的是文件夾是pretrain_model,必不可少的,這裏面存放的VGG_imagenet.npy也就是VGG模型,這個大家在網上找找就能找到。還有一個cache文件夾是隨着訓練的進行,用來存放訓練數據的,爲了下次加載數據方便。

experiments---->下面有個scripts文件夾裏面存放的是faster_rcnn_end2end.sh,算是起始指令吧,我們是通過運行這個文件,加載參數來調用其他各個文件的。

lib------------>該文件夾裏面存放的東西很多,主要是一些python接口文件及運行的log文件。所以說程序運行之前先make一下。關於裏面各個作用,下面我會根據訓練流程一一講解。

output-------->存放當然是你的輸出結果了,你的訓練結束後所訓練好的模型。

tools------->裏面的是訓練、測試的加載起始文件。demo.py是一個簡單的測試文件。

好了,關於各個文件的說明已經結束。

第二點:faster rcnn訓練流程開始

1.數據加載

通過./experiments/scripts/faster_rcnn_end2end.sh gpu 0  VGG16 pascal_voc命令,調用tools/train_net.py加載完參數後 imdb = get_imdb(args.imdb_name)調用了get_imdb()函數(該函數來於lib/datasets/factory.py)返回的是一個lambda表達式(其實是通過pascal_voc()函數來創建imdb數據的,通過該表達式,進入了pascal_voc函數,初始化了imdb數據,此時,數據加載完成。---->self._roidb_handler = self.gt_roidb並設置了gt_roidb

2.得到最初的roidb數據

然後返回train_net.py函數中執行 roidb = get_training_roidb(imdb)其中要調用imdb.append_flipped_images()函數,這個是基類的imdb的成員函數。在這個函數裏面,對所有圖像的for循環裏,調用了self.roidb()函數(boxes = self.roidb[i]['boxes'].copy()),這個時候就會調用imdb的roidb函數,roidb函數檢查類成員_roidb是否爲空,如果不是空直接返回,否則調用roidb_db_handler()函數,因已經設了gt_roidb,實際執行了gt_roidb()函數,這個函數是在pascal_voc類。gt_roidb函數通過load_pascal_annotation()讀取pascal_voc的標註。形成的roidb格式爲:

list[

dict1(for image 1):

{ 'boxes' : (np.array,(N,4),左上角和右下角頂點座標,從0開始)

  'gt_classes': (np.array,(N,),每個框的類別號,21類--0到20中的數字)

  'gt_overlaps':(np.array,(N,21),稀疏矩陣,每個框對應的那一類爲1,其他是0)

  'seg_areas':(np.array,(N,),每個框的面積)

   'flipped':False}

dict2(for image 2):

{

}..................

...]

在這裏append_flipped_images就是對每張圖片的每個框都做一個水平對稱變換(加強數據集),即x座標變,y座標不變。最終就是gt_roidb的長度加倍。接着回到get_training_roidb(imdb)函數中,往下執行。由於HAS_RPN=True,IS_MULTISCALE=False.因此調用rdl_roidb(即roi_data_layer文件夾中的roidb文件)的prepare_roidb(imdb)函數,進一步添加roidb數據的字段。)

list[

dict1(for image 1):

{ 'boxes' : (np.array,(N,4),左上角和右下角頂點座標,從0開始)

  'gt_classes': (np.array,(N,),每個框的類別號,21類--0到20中的數字)

  'gt_overlaps':(np.array,(N,21),稀疏矩陣,每個框對應的那一類爲1,其他是0)

  'seg_areas':(np.array,(N,),每個框的面積)

   'flipped':False

    'Image':當前圖像的路徑

    'width':圖像的寬度

    'height':圖像的高度

    'max_classes':(np.array,(N,),每個框與gt的overlap最大的類別號,就是類別標號)

    'max_overlaps':(np.array,(N,),全1)}

dict2(for image 2):

{

}..................

...]

小總結:1.2完成後返回了最終的imdb、roidb對象。注意這兩部一定要好好結合pascal_voc.py(後續我會繼續更新這部分代碼的理解)文件進行理解。

3.調用train_net()函數爲roidb添加字段

接下來開始真正調用train.py文件中的train_net函數了 roidb = filter_roidb(roidb)roidb要先經過篩選,該函數的作用是刪除沒有用的roidb數據,具體判決:檢查每個圖像中至少有一個前景roi(overlap大於0.5)或背景的roi(overlap大於等於0小於0.5),這樣imdb和roidb就完全準備好了。開始調用train_net函數。

train_net函數中,需要構造solver對象,而solver類在初始化時需要繼續對roidb添加更多的信息,涉及到的函數是self.bbox_means, self.bbox_stds = rdl_roidb.add_bbox_regression_targets(roidb)即rdl_roidb中的add_bbox_regression_targets函數,在該函數中,可以看到爲每個圖像的roidb中加入了“bbox_targets"字段,調用的函數爲_compute_targets(),該函數的輸入參數爲:

rois :   'boxes' : (np.array,(N,4),左上角和右下角頂點座標,從0開始)

'max_classes':(np.array,(N,),每個框與gt的overlap最大的類別號,就是類別標號)

'max_overlaps':(np.array,(N,),全1

其實這裏調用這個函數沒有什麼意義。因爲這裏全是groundtruth的bbox,而這個_compute_targets函數我們稍後會看到它是一個計算迴歸偏移量的。而gt的bbox傳進去,計算的偏移量當然是0。因此可以看到添加的bbox_targets字段是一個(N,5)的矩陣,第一列是類別,後面四列是迴歸偏移量,在這裏全是0。這裏只要知道一下被添加了一個字段就好了。下面開始調用solver的train_model函數。

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