1. 程式人生 > >深度學習經典目標檢測例項分割語義分割網路的理解之五 MASK-RCNN

深度學習經典目標檢測例項分割語義分割網路的理解之五 MASK-RCNN

我不生產博文,我是CSDN的搬運工。

本文參考了下面這幾篇部落格:

基於最早的 Faster RCNN 框架,出現不少改進,主要有三篇需要看:

1)作者推薦的這篇

     Speed/accuracy trade-offs for modern convolutional object detectors

     論文下載arxiv

2)ResNet

     MSRA也算是作者自己的作品,可以 refer to blog【ResNet殘差網路】 

     論文下載arxiv

3)FPN

     Feature Pyramid Networks for Object Detection,通過特徵金字塔來融合多層特徵,實現CNN。

     論文下載arxiv

改進

好了,繼續這一系列的整理,mask-rcnn更進一步,利用之前的網路框架又添加了語義分割的功能。

Mask-RCNN 來自於年輕有為的 Kaiming 大神,通過在 Faster-RCNN 的基礎上新增一個分支網路,在實現目標檢測的同時,把目標畫素分割出來。

       Mask-RCNN 的網路結構示意:


        

假設大家對 Faster 已經很熟悉了,不熟悉的同學建議先看下之前的博文:【目標檢測-RCNN系列

       其中 黑色部分為原來的 Faster-RCNN,紅色部分為在 Faster網路上的修改:

1)將 Roi Pooling 層替換成了 RoiAlign;

2)新增並列的 FCN 層(mask 層);

       先來概述一下 Mask-RCNN 的幾個特點(來自於 Paper 的 Abstract):

1)在邊框識別的基礎上新增分支網路,用於 語義Mask 識別;

2)訓練簡單,相對於 Faster 僅增加一個小的 Overhead,可以跑到 5FPS;

3)可以方便的擴充套件到其他任務,比如人的姿態估計 等;

4)不借助 Trick,在每個任務上,效果優於目前所有的 single-model entries;

來看下 後面兩種 RCNN 方法與 Mask 結合的示意圖(直接貼原圖了):

        

       圖中灰色部分是 原來的 RCNN 結合 ResNet or FPN 的網路,下面黑色部分為新新增的並聯 Mask層,這個圖本身與上面的圖也沒有什麼區別,旨在說明作者所提出的Mask RCNN 方法的泛化適應能力 - 可以和多種 RCNN框架結合,表現都不錯


關鍵點

ROIAlign

問題

  1. 做segment是pixel級別的,但是faster rcnn中roi pooling有2次量化操作導致了沒有對齊,因而產生了漂移出的誤差。
    這裡寫圖片描述

  2. 兩次量化,第一次roi對映feature時,第二次roi pooling時(這個圖參考了youtube的視訊,但是感覺第二次量化它畫錯了,根據上一講ross的原始碼,不是縮小了,而是部分bin大小和步長髮生變化) 
    這裡寫圖片描述

  3. RoIWarp,第一次量化了,第二次沒有,RoIAlign兩次都沒有量化 
    這裡寫圖片描述

解決方案

和上一講faster rcnn舉的例子一樣,輸出7*7

  1. 劃分7*7的bin(我們可以直接精確的對映到feature map來劃分bin,不用第一次量化) 
    這裡寫圖片描述

  2. 每個bin中取樣4個點,雙線性插值 
    這裡寫圖片描述

則第一個bin 的值應該為2+2+7+7 除以4 = 4.5,對於每個bin,RoIAlign只用了4個值求平均。

  1. 對每個bin4個點做max或average pool

# pytorch
# 這是pytorch做法先採樣到14*14,然後max pooling到7*7
pre_pool_size = cfg.POOLING_SIZE * 2
grid = F.affine_grid(theta, torch.Size((rois.size(0), 1, pre_pool_size, pre_pool_size)))
crops = F.grid_sample(bottom.expand(rois.size(0), bottom.size(1), bottom.size(2), bottom.size(3)), grid, mode=mode)
crops = F.max_pool2d(crops, 2, 2)
# tensorflow
pooled.append(tf.image.crop_and_resize(
                feature_maps[i], level_boxes, box_indices, self.pool_shape,
                method="bilinear"))

@爆米花好美啊 還提及了一種線性插值的方法,顯然更準確,也顯然計算更復雜。自己看著辦吧。

關鍵點2 Lmask

L = L_cls + L_box + L_mask

在訓練階段,我們對每個樣本的 RoI 定義了多工損失函式  ,其中 L_cls 和 L_box 的定義和Fast R-CNN 是一樣的。在 mask 分支中對每個 RoI 的輸出是 K*m*m,表示K個 尺寸是 m*m的二值 mask,K是物體類別數目。每個 ROIAlign 對應 K*m*m 維度的輸出。K對應類別個數,即輸出K個mask,m對應 池化解析度(7*7)。

Loss 函式定義:Lmask(Cls_k) = Sigmoid (Cls_k), 即 per-pixel sigmoid,平均二值交叉熵(average binary cross-entropy)Loss,通過逐畫素的 Sigmoid 計算得到。

binary_crossentropy
  即對數損失函式,log loss,與sigmoid相對應的損失函式。

  公式:L(Y,P(Y|X)) = -logP(Y|X)

  該函式主要用來做極大似然估計的,這樣做會方便計算。因為極大似然估計用來求導會非常的麻煩,一般是求對數然後求導再求極值點。損失函式一般是每條資料的損失之和,恰好取了對數,就可以把每個損失相加起來。負號的意思是極大似然估計對應最小損失。


公式1


公式1合併後的公式

注:我們的 L_mask 只定義對應類別的 mask損失,其他類別的mask輸出不會影響該類別的 loss。

我們定義 L_mask 的方式使得我們的網路在生成每個類別的 mask 不會受類別競爭影響,解耦了mask和類別預測。

Why K個mask?

通過對每個 Class 對應一個 Mask 可以有效避免類間競爭(其他 Class 不貢獻 Loss )。


通過結果對比來看(Table2 b),也就是作者所說的 Decouple 解耦,要比多分類 的 Softmax 效果好很多。

3.1. Implementation Details 
Training: 對於 mask loss L_mask 只在正樣本的 RoIs 上面定義。 
我們採用文獻【9】的影象-中心 訓練方法。將影象長寬較小的一側歸一化到 800個畫素。在每個 mini-batch 上每個 GPU 有2個影象,每個影象 N個樣本 RoIs,正負樣本比例 1:3.其中 對於 C4 框架的 N=64, 對 FPN框架的 N=512。在8個GPU上訓練,還有其他一些引數設定。

Inference: 在測試階段,C4的候選區域個數是300, FPN 是 1000.對這些候選區域我們進行座標迴歸,再非極大值抑制。然後對前100個得分最高的檢測框進行 mask 分支運算。這樣做可以提高速度改善精度。在 mask 分支中 ,我們對每個 RoI 給出 K 個 mask預測,但是我們只使用 分類分支給出的那個類別對應的 mask。然後我們將 m×m 浮點 mask 歸一化到 RoI 尺寸,使用一個0.5閾值進行二值化。

human pose estimation:

這裡寫圖片描述

  以及文中提到的選擇性搜尋: