深度學習目標檢測系列論文閱讀和Pytorch實現(四)——FCN論文閱讀

FPN論文(https://arxiv.org/abs/1612.03144

特徵金字塔結構是進行多尺度目標檢測常見架構。在論文之前因爲計算量過大很少有相關的檢測器。

一、論文貢獻

1)、提出一種帶有構建各種尺度的高層特徵圖的側連接的自頂向下網絡結構,稱之爲Feature Pyramid Network (FPN)。

這句話有點繞,什麼是自頂向下結構?何爲頂部?何爲底部?對於輸入圖片,使用CNN提取特徵過程中,越往後特徵圖經過池化或者跨步卷積操作越來越小,這個結構就像金字塔結構一樣,輸入圖片出於金字塔底部,包含了原始的圖片信息,越後面的特徵圖層越小或者說越頂端,包含了更加抽象的特徵,更加高級的特徵,整個特徵提取的過程就是常見的bottom up的過程。論文中的top down architecture實際上就是自頂向下,從高級特徵圖利用上採樣或者反捲積等操作,恢復到低一級的特徵圖。然後和之前bottom up的層進行特徵融合。這樣包含了更加豐富的語義信息。解決了CNN中卷積核管中窺豹的不足。不贅述。特種融合是CNN中常見的提升性能漲點方式。

二、簡介

上圖總結了多尺度的常見操作:

a)、通過輸入圖片resize到不同尺度,然後分別獨立計算,一個字:慢。

b)、常見的CNN提取輸入圖像特徵然後預測。Faster RCNN之類使用該架構。

c)、利用特徵提取網絡中間層進行多尺度預測,例如SSD就是通過該結構漲點很多。

d)、本文提出的架構,左邊是常見的特徵提取過程,右邊是top down結構,從高層語義通過上採樣恢復低層。中間通過lateral connection連接。實現不同層,不同尺度特徵的融合。更魯邦、更加豐富的語義,用作者的話說是semantically stronger features。

上圖兩種結構區別:

上方) 帶有跳連結構的自頂向下架構,預測通過最優層作出。

下方)論文提出的架構,所有層獨立預測。

論文提出的側連接(lateral connection )和自頂向下分支(top-down pathway )是通過逐元素相加(element-wise addition)實現特徵融合。

  • 自底向上分支

該路徑爲主幹網絡(backbone ConvNet)前向傳播路徑。該分支計算獲得尺度爲輸入圖片2階乘縮放的特徵圖。

在這些輸出特徵圖中有很多具有相同的大小,我們稱這些特徵圖在網絡的同一stage。對於論文提出的特徵圖金字塔結構,我們定義一個stage中的網絡層爲同一金字塔級別(one pyramid level for each stage )。我們選擇每一stage的最後一層輸出特徵作爲我們FPN的特徵圖,用於構建特徵金字塔。其實這個想法是比較自然的,因爲每一stage的最後一層特徵圖往往具有這一階段最佳的特徵。

對於ResNet系列網絡(上圖),作者提出使用每個stage的最後一個卷積塊(residual block)的激活輸出構建金字塔結構。

原文:

We denote the output of these last residual blocks as {C2, C3, C4, C5} for conv2, conv3, conv4, and conv5 outputs, and note that they have strides of {4, 8, 16, 32} pixels with respect to the input image.

不使用C1是因爲C1的特徵圖尺寸很大,計算量開銷過大,比如SSD中也是僅僅對後面幾個stage的特徵圖做多尺度預測。太底層的特徵圖計算量呈現指數增加。

  • 自頂向下分支和側連接

    對高層特徵進行粗略的上採樣(nearest neighbor upsample),獲得和低一級特徵圖相同的尺寸,通過側連接和前向傳播的特徵相加進行融合。

    具體實現結構見Figure3

    bottom-up的特徵圖{C2, C3, C4, C5}經過1x1卷積(256個)先進行降維,top的特徵圖通過上採樣,然後兩者相加。所有的側連接都使用了256個1x1卷積核進行降維。最後對融合的特徵圖使用3x3卷積(平滑上採樣的鋸齒等)獲得最終特徵圖{P2, P3, P4, P5 }。值得注意的是這些額外層並未引入非線性!

    Pytorch中的實現:

  • # Bottom-up
    c1 = self.RCNN_layer0(im_data)
    c2 = self.RCNN_layer1(c1)
    c3 = self.RCNN_layer2(c2)
    c4 = self.RCNN_layer3(c3)
    c5 = self.RCNN_layer4(c4)
    # Top-down
    p5 = self.RCNN_toplayer(c5)
    p4 = self._upsample_add(p5, self.RCNN_latlayer1(c4))
    p4 = self.RCNN_smooth1(p4)
    p3 = self._upsample_add(p4, self.RCNN_latlayer2(c3))
    p3 = self.RCNN_smooth2(p3)
    p2 = self._upsample_add(p3, self.RCNN_latlayer3(c2))
    p2 = self.RCNN_smooth3(p2)
    
    p6 = self.maxpool2d(p5)
    
    rpn_feature_maps = [p2, p3, p4, p5, p6]

    其中_upsample_add函數實現上採樣並求和:

  • def _upsample_add(self, x, y):
            _,_,H,W = y.size()
            return F.upsample(x, size=(H,W), mode='bilinear') + y

     

發佈了12 篇原創文章 · 獲贊 6 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章