1. 程式人生 > 實用技巧 >FPN(Feature Pyramid Network)基礎概念

FPN(Feature Pyramid Network)基礎概念

論文來源:https://arxiv.org/abs/1612.03144

1.簡介

  作者開發了一種具有橫向連線的自頂向下架構,用於在所有尺度上構建高階語義特徵對映。這種FPN架構在幾個應用程式中作為通用特徵提取器表現出了顯著的改進。包括一個自下而上的通道,自上而下的連線和橫向連線,如下所述。

  優勢:在幾乎不增加額外計算量情況下解決多尺度檢測問題,提高了準確性(尤其是影象中的小物體檢測)。

  下面簡單介紹幾種特徵提取結構:

  

  a.對某一輸入圖片我們通過壓縮或放大從而形成不同維度的圖片作為模型輸入,使用同一模型對這些不同維度的圖片分別處理後,最終再將這些分別得到的特徵(feature maps)組合起來就得到了我們想要的可反映多維度資訊的特徵集

此種方法缺點在於需要對同一圖片在更改維度後輸入處理多次,因此對計算機的算力及記憶體大小都有較高要求

  b.則只拿單一維度的圖片做為輸入,然後經CNN模型處理後,拿最終一層的feature maps作為最終的特徵集。顯然此種方法只能得到單一維度的資訊。優點是計算簡單,對計算機算力及記憶體大小都無過高需求。此方法為大多數R-CNN系列目標檢測方法所用像R-CNN/Fast-RCNN/Faster-RCNN等。因此最終這些模型對小維度的目標檢測效能不是很好。

  c.同樣是拿單一維度的圖片做為輸入,不過最終選取用於接下來分類或檢測任務時的特徵組合時,此方法不只選用了最後一層的high level feature maps,同樣也會選用稍靠下的反映圖片

low level 資訊的feature maps。然後將這些不同層次(反映不同level的圖片資訊)的特徵簡單合併起來(一般為concat處理),用於最終的特徵組合輸出。此方法可見於SSD當中。不過SSD在選取層特徵時都選用了較高層次的網路。比如在它以VGG16作為主幹網路的檢測模型裡面所選用的最低的Convolution的層為Conv4,這樣一些具有更低級別資訊的層特徵像Conv2/Conv3就被它給漏掉了,於是它對更小維度的目標檢測效果就不大好。

  d.同圖(c)中的方法有些類似,也是拿單一維度的圖片作為輸入,然後它會選取所有層的特徵來處理然後再聯合起來做為最終的特徵輸出組合。即在圖c的基礎上,加上了一個自頂向下的特徵融合操作:對高層次進行上取樣,得到較大的特徵圖(等於下層特徵圖的維度)。然後將結果與下層特徵圖相加(

add)。

2.詳細結構

    

  2.1自下而上模組

  對輸入的影象逐層進行CNN提取特徵,結果是較底的層反映較淺層次的圖片資訊特徵像邊緣等;較高的層則反映較深層次的圖片特徵像物體輪廓、乃至類別等。

  2.2自上而下模組

  上層的特徵輸出一般其 size比較小,但卻能表示更強的的圖片語義資訊,但是,size較大等得特徵層也不是沒有作用,需要按一定的比例結合這兩方面的資訊。具體做法是:

    (1)最上一層的特徵層經過1*1卷積層降維度,然後進行下采樣(2倍)。

    (2)將左邊的次上層經過1*1卷積降維,與(1)的結果相加操作。

  Tip:每一層的結果都可以提供預測

3.程式碼參考

ResNet後新增FPN部分實現)

# 返回值是5個計算後的特徵圖

# 丟棄C1(卷積引數太大)
_, C2, C3, C4, C5 = resnet_graph(input_image, "resnet101", stage5=True)

# 從上而下模組
# KL=keras.layers 
P5 = KL.Conv2D(256, (1, 1), name='fpn_c5p5')(C5)
P4
= KL.Add(name="fpn_p4add")([ KL.UpSampling2D(size=(2, 2), name="fpn_p5upsampled")(P5), KL.Conv2D(256, (1, 1), name='fpn_c4p4')(C4)])
P3
= KL.Add(name="fpn_p3add")([    KL.UpSampling2D(size=(2, 2), name="fpn_p4upsampled")(P4),    KL.Conv2D(256, (1, 1), name='fpn_c3p3')(C3)]) P2 = KL.Add(name="fpn_p2add")([ KL.UpSampling2D(size=(2, 2), name="fpn_p3upsampled")(P3), KL.Conv2D(256, (1, 1), name='fpn_c2p2')(C2)]) # 把每個{Pk}層都乘以一個3*3的卷積生成特徵圖 P2 = KL.Conv2D(256, (3, 3), padding="SAME", name="fpn_p2")(P2) P3 = KL.Conv2D(256, (3, 3), padding="SAME", name="fpn_p3")(P3) P4 = KL.Conv2D(256, (3, 3), padding="SAME", name="fpn_p4")(P4) P5 = KL.Conv2D(256, (3, 3), padding="SAME", name="fpn_p5")(P5) #橫向連線生成特徵圖 mrcnn_feature_maps = [P2, P3, P4, P5] # P6 is used for the 5th anchor scale in RPN. #P6 = KL.MaxPooling2D(pool_size=(1, 1), strides=2, name="fpn_p6")(P5) #rpn_feature_maps = [P2, P3, P4, P5, P6]