1. 程式人生 > >faster-rcnn-tf版網路流程詳解

faster-rcnn-tf版網路流程詳解

faster-rcnn論文連線:https://arxiv.org/pdf/1506.01497.pdf

程式碼地址:https://github.com/zacks417/faster-rcnn-tf

按照論文思路並參考了其他版本的原始碼,這版程式碼是我加過註釋的tf版本,在我自己的電腦上能跑通。

本機實驗環境:py3.6, CUDA9.0, tf1.7,GTX1070。

下面講解一下faster-rcnn整體網路流程

以VGG16為backbone來講解faster-rcnn整體流程

以vgg網路輸入為**600x800x3**為例,網路的**conv5_3**為rpn網路的輸入,就是上圖中的feature Map, 大小為**1x38x50x512**

,backbone部分就不講了,比較簡單.

RPN部分:

下圖為rpn的結構圖,輸入即為conv5_3,輸出rois(128x84)128個感興趣區域,84為21x4,即為每個類別都預測bbox。

conv5——3首先通過3x3 same卷積降維,記為rpn_conv,維度變成1x38x50x512,接下去是兩個分支,都用的1x1卷積,數量分別為anchorsx2(前景後景),x4(兩個點座標)。

下面分支**rpn_bbox_pred**(1x38x50x36)為預測框的座標和anchor的offset。

上面rpn_cls_score(1x38x50x18,這裡最後為18,9x2,是包含了背景的,一會計算標籤hloss會去掉背景)為分類得分圖,最上面分支中通過加入地面真實框、影象高寬資訊、網路總步長、總anchors數量(9)通過anchor_target_layer層生成rpn_label(1x1x38x50),這個函式在程式碼檔案 ./layer_utils/anchor_target_layer中,該函式同時還生成rpn_bbox_targets(anchor和gt_box之間的offset迴歸目標)以及相對應的權重rpn_bbox_inside_weights,rpn_bbox_outside_weights,等會用於計算rpn_loss_box和rpn_cross_entropy。

然後是rpn_cls_score下面這個分支做一次reshape為rpn_cls_score_reshape(維度1x38x(50x9)x2,這個去除掉-1的標籤之後與rpn_label求交叉softmax損失),便於做softmax二分類,接著reshape成[38x50x9,2]在第二個維度2上進行argmax求索引,為類別預測結果rpn_cls_pred維度為(38x50x9,);

將rpn_cls_score_reshape在最後一個維度(2)上做softmax二分類為rpn_cls_prob_reshape(維度為1x38x(50x9)x2)然後再把這個9 reshape回去為rpn_cls_prob(維度1x38x50x18)

此時加入地面真實框、影象高寬、網路步長、總anchor數(9)、之前預測的rpn_bbox_pred通過一層proposal_layer生成rois和對應的rois_scores(nms之前先按得分排序選取前12000個,nms後剩餘2000個proposal)(2000x5,5是序號+兩個座標)。


然後再加入地面真實框和類別數(20+1背景也算一類而且是序號0)經過proposal_target_layer生成rois(128x84,21x4每個類別都有座標),同時還會生成_proposal_targets字典,存放rois、labels、bbox_targets、bbox_inside_weights、bbox_outside_weights,等會用來計算RCNN的損失反過來進行修正。到此,rpn網路已經產生輸出建議區域。

下面先列一下rpn網路的兩個損失,之前都有提到過:

RPN分類損失

rpn_cross_entropy = tf.reduce_mean(tf.nn.sparse_softmax_cross_entropy_with_logits(logits=rpn_cls_score,labels=rpn_label))

RPN迴歸損失

這裡是計算預測框的座標和anchors的offset 和 anchors和地面真實框的offset,兩個offset的差值作為迴歸目標,用smooth-l1損失計算
rpn_loss_box = self._smooth_l1_loss(rpn_bbox_pred,rpn_bbox_targets,rpn_bbox_inside_weights,rpn_bbox_outside_weights,sigma=sigma_rpn,dim=[1,2,3])

ROIPooling部分,如下圖所示,前面rpn生成的rois感興趣區域中有兩個座標點,將它對映到conv5-3的特徵圖上即為感興趣區域,對這一部分進行池化,_crop_pool_layer函式在network.py中這版程式碼沒有實現ROI Pooling layer 而是把ROI對應的特徵圖resize成相同尺寸(14x14)後再進行 max pooling(之後是7x7)生成pool5。 (後面tf直接有mask-rcnn提出的ROIAlign中採用的雙線性插值的裁剪圖片方法tf.image.crop_and_resize(images, boxes, batch_inds,[pooled_height, pooled_width], method='bilinear', name='Crop'))

RCNN分類和迴歸:

輸入是之前的pool5(128x7x7x512),經過兩層全連線層(後接relu)然後分別用全連線層生成目標框預測結果bbox_pred(128x4)、全連線層後接softmax生成類別預測結果cls_prob(128x21),這裡可以理解為全連線層生成結果對RPN生成的結果進行修正。結構如下圖所示

 

下面介紹一下RCNN的損失,也是兩類

分類損失

這裡的輸入是最後全連線層的輸出,沒有經過softmax的(對應tf.nn.sparse_softmax_cross_entropy_with_logits這個函式),標籤是RPN網路最後proposal_target_layer生成的label
cross_entropy = tf.reduce_mean(tf.nn.sparse_softmax_cross_entropy_with_logits(logits=cls_score,labels=label))


迴歸損失

輸入一個為最後全連線層的輸出,另一個為RPN最後的bbox輸出,用來對RPN輸出的bbox進行修正。
loss_box = self._smooth_l1_loss(bbox_pred,bbox_targets,bbox_inside_weights,bbox_outside_weights)

 

至此,faster-rcnn一整套流程均完結,更詳細的實現可看原始碼,我在程式碼中均加入了註釋便於理解。

此外論文中提到的交替訓練我這裡並沒有實現,我採用的是end-to-end訓練方法,以後有時間再把交替訓練的方法加進去。