mask rcnn 論文閱讀筆記
Mask RCNN閱讀筆記
目錄
一. 文章主題介紹:
該文章主要是通過擴充套件Faster RCNN,實現例項分割的功能;具體來說,就是在後面添加了一個mask分支用於畫素級別的預測(也就是例項分割)。如下圖所示:
這個分支僅僅增加很好的計算的消耗
論文作者:Kaiming He(first),CVPR 2017的會議best paper。
二. 文章核心設計:
2.1 mask分支損失函式的計算
新的思想:
1. 不同於FCNs系列的工作——每個畫素即預測類別也預測是否被為物件;而Mask RCNN 分離 了每個畫素是物件以及屬於哪個類別的預測——類別預測直接從類別預測Cls分支中讀取。
2. 這種分離的預測存在另一種特性:就是畫素級的預測掩碼(mask)沒有類別競爭。
mask分支的執行: mask分支的輸出為針對每個RoI 有一個-dimensional輸出。掩碼為二值掩碼——只有0或1。只用來預測該畫素級別的點是否為物件。
Mask 分支程式碼設計示例:
class Model ...
# 前層輸出(N,1024,7,7)
self.out_mask =
nn.Sequential(
nn.ConvTranspose2d(self.out_channels,
256, kernel_size=2, stride=2), #(N,256,14,14)
nn.ReLU(inplace=True) ,
nn.Conv2d(256, nb_classes - 1, kernel_size=1, stride=1),
# (N,20,14,14) VOC 資料集,20個類別
nn.Sigmoid(), # sigmoid啟用
)
mask分支的損失計算: 利用平均二值交叉驗證損失函式 (binary cross-entroy loss) ,並且根據每個RoI所關聯的類別k,只計算該類別k對應的mask損失計算,其他非k的mask不參與損失計算,也就是每個ROI只計算(1,1,m,m)大小的損失。
損失程式碼:
class class_loss_mask(nn.Module):
def __init__(self, obj_classes=20):
super(class_loss_mask, self).__init__()
self.obj_classes = obj_classes
def forward(self, preds, targets):
'''
:param preds: (num_rois,num_class,pool,pool)=(20,14,14)
:param targets: (num_rois,num_class,pool,pool)
:return:
'''
weight = targets[:, :self.obj_classes, :, :]
y_true = targets[:, self.obj_classes:, :, :]
weight = Variable(torch.from_numpy(weight).float()).cuda()
y_true = Variable(torch.from_numpy(y_true).float()).cuda()
preds = preds * weight #用於遮蔽非k的類別的損失計算,只計算有效類別的損失
N = torch.sum(weight)
return F.binary_cross_entropy(preds, y_true, size_average=False) / N
2.2 ROIAlign的一些改進
1.該技術要解決的問題描述:
[12,18]說明了ROIPooling是粗糙的對齊,ROIPooling存在兩個量化階段:
RoI邊界量化階段:原圖box與RoI之間的量化, RoIPooling主要採用round[x/16]的方式,16是特徵圖的步長。
ROI到Pool盒(bin)階段:RoI與提取的特徵之間的量化,特徵圖(h,w) –> (pool,pool)pool=7或14。作為後面Fast RCNN階段的輸入。
這兩種量化階段導致了RoI與提取的特徵之間的錯位(misalignment)問題。
2.具體的實現:
1)為了修復這種不對齊的方式,針對兩個量化階段進行修改,在RoI邊界和pool盒(box)階段避免任何量化:
用 x/16代替[x/16],即對步長不做round操作。
對每個RoI在四個位置上執行bilinear interpolation(雙線差值法)操作,然後再用max或者average pool操作。
2)關鍵程式碼如下所示:
class RoIAlign: ....
region = x_img[:, :, y:(y + h + 1), x:(x + w + 1)]
region = F.upsample_bilinear(region, (h, w)) # 對RoI使用bilinear操作
region = self.adaptive_max_pool(region)
2.3 兩種基礎網路
為了驗證Mask RCNN的一般性,它的backbone使用了ResNet和FPN兩種型別的基礎網路架構用於提取特徵,兩個結構對應的mask 分支的示意圖:
FPN獲得的效能優於ResNet的效能;主要是FPN使用金字塔特徵結構,將low-level的特徵與high-level的特徵融合,能提取更加準確的位置等特徵資訊。
三. 打磨實驗:
3.1 實驗引數的配置:
引數 | 值 |
---|---|
min_side | 800 pixels |
pos:neg | 1:3 |
learning_rate | 0.02(160k),0.002(120k) |
weight_decay | 0.0001 |
momentum | 0.9 |
gradient method | SGD |
RoI數目(ResNet/FPN) | (64/512) |
anchors | 5 scales ,3 aspect ratios |
mini_batch | 16 (on 8 GPUs) |
training set | COCO (80 classes) |
—test—- | |
proposal number | 300(ResNet), 1000(FPN) |
mask branch | 取得分top 100的RoI對應的mask輸出 |
mask threshold | 0.5 就是預測大於0.5的標位1 |
3.2 主要的一些對比實驗
(實驗圖片來自於原始論文)
1. 基礎網路結構ResNet和FPN的對比
1)網路深的比淺的效能高 (然而,根據論文,對於物件檢測系統來說不一定越深的、越先進的網路效能就越好)
2)FPN backbone優於ResNet的backbone .
2. FCNs系列的聯合預測方式與Mask RCNN這種分離的預測方式對比
1)實驗結果表明,這種分離的預測方式比FCNs系列效能好的多,其他分支確定類別和box,而mask只需要預測二值掩碼即可(sigmoid+binary loss)
3. 類別指定和類別不可知的mask方式的對比(也就是求mask時是否利用cls分支的結果選擇對應的mask進行解析)
1)如下圖所示的對比實驗,結果為Class-Specific .vs Class-Agnotic——30.3 AP vs 29.7 AP,表明了分離的mask分支獨立有效性 (不知理解是否正確,有待考察)
4. RoIAlign與RoIPool,RoIWarp等方式的對比
1) 各個資料表明,RoIAlign優於ROIPool
2) RoIAlign 對max或者average pool不敏感
3) 對於更大的32跨度的結構,RoIAlign優勢更加突出,表明RoIAlign一定程度改善大跨度的問題
4) 對於FPN backbone的網路結構,RoIAlign在物件識別的方面表現優勢不明顯,而在關鍵點檢測方面,表現很明顯 (第二、三個表)
5. Mask分支使用MLP還是使用FCN結構(全卷積層)的對比
1) 使用FCN結構作為mask分支表現優於MLP,因為卷積層保持了空間佈局的資訊。
6. Mask RCNN與其他前沿工作的對比
1) 與FCIS和MNC工作的對比,Mask RCNN的效能明顯要好
2) 如下面效果圖展示,FCIS存在systematic artifacts——也就是掩碼中存在一些雜質,瑕疵。而Mask RCNN沒有這種問題 (如紅圈標註)
7. mask 分支對檢測框預測的影響
1) Mask 分支對Box的預測有一定的提升,可能是多工訓練的原因。
2) 通過列表觀察可以發現,Mask 的AP和Box AP很相近,表明Mask RCNN拉近了box預測和更加有挑戰性的例項分割預測的距離。
四. 收穫/總結/啟發:
1) 提出了一種新的思想,將畫素級的預測——分離類別預測和掩碼預測**
2) 為了解決RoIPool錯位問題,提出了RoIAlign 層——使用x/16而不是[x/16]和使用bilinear取樣避免ROI量化**
補充說明
注:(一些網頁需要外網VPN連結)