深度學習目標檢測之 R-CNN 系列:Faster R-CNN 網絡詳解

深度學習目標檢測之 R-CNN 系列:Faster R-CNN 網絡詳解

深度學習目標檢測之 R-CNN 系列包含 3 篇文章:

1. 前言

這一篇文章主要是深入的理解 Faster R-CNN 網絡結構。

爲了深入的瞭解 Faster R-CNN,我這裏 clone 了一份 caffe 版本的 py-faster-rcnn,方便查看源代碼。如果編譯過程遇到 CUDNN 版本問題,可以參考 Caffe編譯時提示 CUDNN 版本不兼容的解決辦法

如果想對 Faster R-CNN 文件層次有更深入的認識,可以參考 Faster RCNN算法demo代碼解析

2. Faster R-CNN 網絡概覽

下圖大致描述了 Faster R-CNN 的過程。

下面這幅圖可能更清楚的表達了 Faster R-CNN 是如何工作的。只是需要注意的是下圖是 test 網絡。

    1. 將圖片輸入 CNN 網絡(比如 ZF/VGG 等預訓練好的分類模型),得到 feature maps;
    1. 將 feature maps 喂入 RPN(Region Proposal Network) 網絡得到 region proposals (包含第一次迴歸)。更具體的,RPN 首先生成一堆Anchor box,對其進行裁剪過濾後通過 softmax 判斷 anchors 屬於前景(foreground)或者背景(background),即是不是物體,所以這是一個二分類任務;同時,另一分支 bounding box regression 修正(迴歸) anchor box,形成較精確的 proposal,注意這並是最後得到的 proposal,後面還會再進行第二次迴歸;
    1. 將上兩步的輸出:feature maps 和 region proposals 喂入 RoI Pooling 層得到統一 size 的 feature maps;
    1. 將 3 輸出的 feature maps 輸入全連接層,利用 Softmax 進行具體類別的分類,同時,利用 L1 Loss 完成 bounding box regression 迴歸(第二次迴歸)操作獲得物體的精確位置。

3. CNN

這裏的 CNN 網絡也可以叫做 conv layers,因爲就是 conv + ReLU + Pooling 的組合,是沒有 fc 層的。以 VGG16(13 個 conv + 3 個 fc) 爲例,這裏僅僅保留了其 13 個 conv 層。

4. RPN

下圖是 RPN 網絡圖,通過兩個 1x1 的卷積層(conv)將 feature map 的 channel 分別變爲 18 和 36,分別用來做分類和 bonding box 迴歸。這裏面最爲關鍵的 layer 就是 rpn-data,幾乎所有核心的功能也都是在這個 layer 中完成。

4.1 rpn-data layer

下面我們來重點看一下 rpn-data layer。

layer {
  name: 'rpn-data'
  type: 'Python'
  bottom: 'rpn_cls_score'
  bottom: 'gt_boxes'
  bottom: 'im_info'
  bottom: 'data'
  top: 'rpn_labels'
  top: 'rpn_bbox_targets'
  top: 'rpn_bbox_inside_weights'
  top: 'rpn_bbox_outside_weights'
  python_param {
    module: 'rpn.anchor_target_layer'
    layer: 'AnchorTargetLayer'
    param_str: "'feat_stride': 16"
  }
}

這裏的 rpn-data 的類型是 AnchorTargetLayer。具體的代碼可以參考

py-faster-rcnn/lib/rpn/anchor_target_layer.py

關於 AnchorTargetLayer 的解讀可以參考:

總的來說,這層幹了如下這些事情。

  • 生成 anchor,並將超出圖像區域的anchor去除,得到有效的 anchor;

  • 給每一個 anchor 分配 label,-1表示忽略該 anchor,0表示背景,1表示前景(物體),得到 labels;

  • 計算 RPN 階段的迴歸目標 bbox_targets;

  • 計算 bbox_inside_weights(將 label 爲 1 的 anchor 權重賦爲 1,其他的都賦爲 0)、bbox_outside_weights(將前景和背景 anchor 的總數記爲 n,則前景和背景 anchor 權重都賦爲 1/n,其它的 anchor 權重都賦爲 0),在計算 SmoothL1Loss 時用於加權;

  • 上述過程得到的 labels, bbox_targets, bbox_inside_weights, bbox_outside_weights,它們第一個維度的長度和有效 anchor 的個數是相同的,最後對它們進行擴充,將無效的 anchor 所對應的 labels, bbox_targets, bbox_inside_weights, bbox_outside_weights 分別加入其中,使這四個輸出的第一個維度的長度等於生成anchor的個數。

4.2 Softmax with Loss

這個是 caffe 標準的 layer, 就是對 softmax 的輸出求 crossentropy loss。對於 RPN 而言就是一個二分類的交叉熵損失函數。

4.3 BBox 迴歸

假設我們對 anchor a 進行迴歸得到 predicated bbox p,那我們歸一化的目標是希望 p 無限接近於 ground true(標記的結果)t。

在二維平面上,從矩形框 p 變換到矩形框 t,顯然就是平移和縮放操作。假設 x,y,w,hx, y, w, h 分別爲 p 的中心座標及寬和高;xa,ya,wa,hax_a, y_a, w_a, h_a 分別爲 a 的中心座標及寬和高;x,y,w,hx^*, y^*, w^*, h^* 分別爲 t 的中心座標及寬和高。那麼從 p 到 a 的變換可以表示如下。

{x=xa+xy=ya+yw=wawh=hah\left\{ \begin{aligned} & x = x_a +\nabla x\\ & y = y_a +\nabla y\\ & w = w_a \cdot \nabla w\\ & h = h_a \cdot \nabla h\\ \end{aligned} \right.

上面的 \nabla 部分都是基於 w,hw, h 計算出來的,表示如下。

{x=watxy=hatyw=waetwh=haeth\left\{ \begin{aligned} & \nabla x = w_a \cdot t_x\\ & \nabla y = h_a \cdot t_y\\ & \nabla w = w_a \cdot e^{t_w}\\ & \nabla h = h_a \cdot e^{t_h}\\ \end{aligned} \right.

其中 tx,ty,tw,tht_x, t_y, t_w, t_h 是預測的偏移量。根據上面的兩個式子可以將其表示如下。

{tx=xxawaty=yyahatw=log(wwa)th=log(hha)\left\{ \begin{aligned} & t_x = \frac {x-x_a}{w_a}\\ & t_y = \frac {y-y_a}{h_a}\\ & t_w = log(\frac {w}{w_a})\\ & t_h = log(\frac {h}{h_a})\\ \end{aligned} \right.

同理。

{tx=xxawaty=yyahatw=log(wwa)th=log(hha)\left\{ \begin{aligned} & t^*_x = \frac {x^*-x_a}{w_a}\\ & t^*_y = \frac {y^*-y_a}{h_a}\\ & t^*_w = log(\frac {w^*}{w_a})\\ & t^*_h = log(\frac {h^*}{h_a})\\ \end{aligned} \right.

這裏需要注意下面幾個問題:

  • 爲什麼上面要用到 ee 或者 loglog,上面可以看到 ee 用來表示 scale 係數,顯然 scale 係數應該大於零,所以用 ee 表示正好可以滿足,那爲什麼用 loglog 呢? loglog 一個很重要的特性就是壓縮大值,也就是說採用這種 loss 可以減小大的目標對最後結果的影響,這樣可以改善模型只能學到大的目標的缺點。

  • 對於 x,yx,y 採用的是線性變化,但是對於 w,hw, h 卻是用的非線性變化,這樣合理嗎?其實當 a 趨近於 t 時,可以認爲 loglog 是線性變化。

4.4 Smooth L1 Loss

Smooth L1 Loss 的數學表達式如下。

f(x)={0.5x2, x<1x0.5, x<1 or x>1 f(x)=\left\{ \begin{aligned} & 0.5x^2, \space |x| < 1 \\ & |x| -0.5, \space x < -1 \space or \ x > 1 \\ \end{aligned} \right.

對於邊框預測迴歸問題,通常也可以選擇平方損失函數( L2 損失),但 L2 範數的缺點是當存在離羣點(outliers) 的時候,這些點會佔 loss 的主要組成部分。比如說真實值爲1,預測 10 次,有一次預測值爲 1000,其餘次的預測值爲 1 左右,顯然 loss 值主要由1000 主宰。所以 Fast RCNN 採用稍微緩和一點的絕對損失函數(smooth L1損失),它是隨着誤差線性增長,而不是平方增長。

注意:smooth L1 和 L1-loss 函數的區別在於,L1-loss 在 0 點處導數不唯一,可能影響收斂。smooth L1 的解決辦法是在 0 點附近使用平方函數使得它更加平滑。

更多內容可以參考 損失函數:L1 loss, L2 loss, smooth L1 loss

5. RoI Pooling

ROI Pooling 的作用是將 RPN 輸出的 region proposal 轉換到相同的 size,然後再喂入 fc 層。RoI Pooling 還有一個進化版本 RoI Align。關於RoI Pooling 和 RoI Align 的介紹可以參考 ROI Pool和ROI Align

6. 損失函數

Faster R-CNN 總共有四個損失函數,RPN 的分類和迴歸損失函數, Fast R-CNN 的分類和迴歸損失函數。RPN 的損失函數上面已經講過,和 Fast R-CNN 的損失函數類似。Fast R-CNN 的分類損失爲多分類交叉損失, 迴歸損失依然爲 smooth L1 loss。

L(pi,ti)=1NclsiLcls(pi,pi)+λ1NregipiLreg(ti,ti) L({p_i},{t_i})= \begin{aligned} & \frac{1}{N_{cls}} \sum_iL_{cls}(p_i, p_i^*) +\lambda \frac{1}{N_{reg}} \sum_ip_i^*L_{reg}(t_i, t_i^*) \\ \end{aligned}

更爲詳細的介紹可以參考 [https://blog.csdn.net/Mr_health/article/details/84970776](【Faster RCNN】損失函數理解).

7. Anchor 的壓縮

在整個過程中對 Anchor 進行了四次壓縮,分別如下:

  • 在最開始劃分 anchor 的時候,忽略超出邊界的 anchor,大約 17000 個左右;
  • 在 RPN 中進行 background(iou < 0.3)和 foreground(iou > 0.7) 劃分時,忽略介於 0.3 和 0.7 之間的 anchor(標記爲 -1);
  • 對每一個預測爲 foreground 的 anchor 的 score,進行排序,保留排名考前的大約 12000 個 anchor;
  • 非極大值抑制(NMS),首先找到 score 最高的 anchor,然後以此 anchor 作爲基準,計算其他的 anchor 與這個 anchor 的 iou,如果 iou 大於閾值,就認爲是同一個目標,直接捨棄這個 anchor,最後大約剩餘 2000 個左右的 anchor。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章