目標檢測中特徵融合技術(YOLO v4)(上)
目標檢測中特徵融合技術(YOLO v4)(上)
論文連結:https://arxiv.org/abs/1612.03144
Feature Pyramid Networks for Object Detection
Tsung-Yi Lin, Piotr Dollár, Ross Girshick, Kaiming He, Bharath Hariharan, Serge Belongie
PANet(Path Aggregation Network)
論文地址:
https://arxiv.org/abs/1803.01534
程式碼地址:
https://github.com/ShuLiu1993/PANet
M2det: A single-shot object detector based on multi-level feature pyramid network
論文地址:
https://arxiv.org/abs/1811.04533
程式碼地址:
https://github.com/qijiezhao/M2Det
Learning Spatial Fusion for Single-Shot Object Detection
,也就是著名的yolov3-asff。
論文地址:
https://arxiv.org/pdf/1911.09516.pdf
程式碼地址:
https://github.com/ruinmessi/ASFF
EfficientDet: Scalable and efficient object detection
。BiFPN思想和ASFF非常類似,也是可學習引數的自適應加權融合,但是比ASFF更加複雜。
論文地址:
https://arxiv.org/abs/1901.01892
程式碼地址:
https://github.com/google/automl/tree/master/efficientdet(Google官方)
https://github.com/zylo117/Yet-Another-EfficientDet-Pytorch(高星PyTorch復現)
特徵融合分類
在深度學習的很多工作中(例如目標檢測、影象分割),
融合不同尺度的特徵
是提高效能的一個重要手段。低層特徵解析度更高,包含更多
位置、細節資訊
,但是由於經過的卷積更少,其
語義性更低,噪聲更多
。高層特徵
具有更強的語義資訊,但是解析度很低,對細節的感知能力較差
。如何將兩者高效融合,取其長處,棄之糟泊,是改善分割模型的關鍵。
很多工作透過融合多層來提升檢測和分割的效能,按照融合與預測的先後順序,分類為
早融合(Early fusion)和晚融合(Late fusion)。
早融合(Early fusion):
先融合多層的特徵,然後在融合後的特徵上訓練預測器(
只在完全融合之後,才統一進行檢測
)。這類方法也被稱為
skip connection,即採用concat、add操作
。這一思路的代表是Inside-Outside Net(ION)和HyperNet。兩個經典的特徵融合方法:
(1)
concat
:系列特徵融合,直接將兩個特徵進行連線。兩個輸入特徵x和y的維數若為p和q,輸出特徵z的維數為p+q;
(2)
add
:並行策略,將這兩個特徵向量組合成復向量,對於輸入特徵x和y,z = x + iy,其中i是虛數單位。
晚融合(Late fusion):
透過結合不同層的檢測結果改進檢測效能(
尚未完成最終的融合之前,在部分融合的層上就開始進行檢測,會有多層的檢測,最終將多個檢測結果進行融合
)。這一類研究思路的代表有兩種:
(1)
feature不融合,多尺度的feture分別進行預測,然後對預測結果進行綜合,
如Single Shot MultiBox Detector (SSD) , Multi-scale CNN(MS-CNN)
(2)
feature進行金字塔融合,融合後進行預測
,如Feature Pyramid Network(
FPN
)等。
接下來,主要對晚融合方法進行歸納總結。
Feature Pyramid Network(FPN)
FPN(Feature Pyramid Network)演算法同時利用低層特徵高解析度和高層特徵的高語義資訊,透過融合這些不同層的特徵達到預測的效果。並且預測是在每個融合後的特徵層上單獨進行的,這和常規的特徵融合方式不同。
FPN將深層資訊上取樣,與淺層資訊逐元素地相加,從而構建了尺寸不同的特徵金字塔結構,
效能優越,現已成為目標檢測演算法的一個標準組件。FPN的結構如下所示。
·
自下而上
:最左側為普通的卷積網路,預設使用ResNet結構,用作提取語義資訊。C1代表了ResNet的前幾個卷積與池化層,而C2至C5分別為不同的ResNet卷積組,這些卷積組包含了多個Bottleneck結構,組內的特徵圖大小相同,組間大小遞減。
·
自上而下
:首先對C5進行1×1卷積降低通道數得到P5,然後依次進行上取樣得到P4、P3和P2,目的是得到與C4、C3與C2長寬相同的特徵,以方便下一步進行逐元素相加。這裡
採用2倍最鄰近上取樣,即直接對臨近元素進行復制,而非線性插值。
·
橫向連線(Lateral Connection)
:目的是為了
將上取樣後的高語義特徵與淺層的定位細節特徵進行融合。
高語義特徵經過上取樣後,其長寬與對應的淺層特徵相同,而通道數固定為256,因此需要對底層特徵C2至C4進行11卷積使得其通道數變為256,然後兩者進行逐元素相加得到P4、P3與P2。
由於C1的特徵圖尺寸較大且語義資訊不足,因此沒有把C1放到橫向連線中。
·
卷積融合
:在得到相加後的特徵後,利用3×3卷積對生成的P2至P4再進行融合,目的是
消除上取樣過程帶來的重疊效應,以生成最終的特徵圖。
FPN對於不同大小的RoI,使用不同的特徵圖,大尺度的RoI在深層的特徵圖上進行提取,如P5,小尺度的RoI在淺層的特徵圖上進行提取,如P2。
FPN的程式碼實現如下:
import torch。nn as nnimport torch。nn。functional as Fimport math
class Bottleneck(nn。Module): expansion = 4 def __init__(self, in_planes, planes, stride=1, downsample=None): super(Bottleneck, self)。__init__() self。bottleneck = nn。Sequential( nn。Conv2d(in_planes, planes, 1, bias=False), nn。BatchNorm2d(planes), nn。ReLU(inplace=True), nn。Conv2d(planes, planes, 3, stride, 1, bias=False), nn。BatchNorm2d(planes), nn。ReLU(inplace=True), nn。Conv2d(planes, self。expansion * planes, 1, bias=False), nn。BatchNorm2d(self。expansion * planes), ) self。relu = nn。ReLU(inplace=True) self。downsample = downsample def forward(self, x): identity = x out = self。bottleneck(x) if self。downsample is not None: identity = self。downsample(x) out += identity out = self。relu(out) return out
class FPN(nn。Module): def __init__(self, layers): super(FPN, self)。__init__() self。inplanes = 64 self。conv1 = nn。Conv2d(3, 64, 7, 2, 3, bias=False) self。bn1 = nn。BatchNorm2d(64) self。relu = nn。ReLU(inplace=True) self。maxpool = nn。MaxPool2d(3, 2, 1)
self。layer1 = self。_make_layer(64, layers[0]) self。layer2 = self。_make_layer(128, layers[1], 2) self。layer3 = self。_make_layer(256, layers[2], 2) self。layer4 = self。_make_layer(512, layers[3], 2) self。toplayer = nn。Conv2d(2048, 256, 1, 1, 0)
self。smooth1 = nn。Conv2d(256, 256, 3, 1, 1) self。smooth2 = nn。Conv2d(256, 256, 3, 1, 1) self。smooth3 = nn。Conv2d(256, 256, 3, 1, 1)
self。latlayer1 = nn。Conv2d(1024, 256, 1, 1, 0) self。latlayer2 = nn。Conv2d( 512, 256, 1, 1, 0) self。latlayer3 = nn。Conv2d( 256, 256, 1, 1, 0)
def _make_layer(self, planes, blocks, stride=1): downsample = None if stride != 1 or self。inplanes != Bottleneck。expansion * planes: downsample = nn。Sequential( nn。Conv2d(self。inplanes, Bottleneck。expansion * planes, 1, stride, bias=False), nn。BatchNorm2d(Bottleneck。expansion * planes) ) layers = [] layers。append(Bottleneck(self。inplanes, planes, stride, downsample)) self。inplanes = planes * Bottleneck。expansion for i in range(1, blocks): layers。append(Bottleneck(self。inplanes, planes)) return nn。Sequential(*layers)
def _upsample_add(self, x, y): _,_,H,W = y。shape return F。upsample(x, size=(H,W), mode=‘bilinear’) + y
def forward(self, x):
c1 = self。maxpool(self。relu(self。bn1(self。conv1(x)))) c2 = self。layer1(c1) c3 = self。layer2(c2) c4 = self。layer3(c3) c5 = self。layer4(c4)
p5 = self。toplayer(c5) p4 = self。_upsample_add(p5, self。latlayer1(c4)) p3 = self。_upsample_add(p4, self。latlayer2(c3)) p2 = self。_upsample_add(p3, self。latlayer3(c2))
p4 = self。smooth1(p4) p3 = self。smooth2(p3) p2 = self。smooth3(p2) return p2, p3, p4, p5
PANet(Path Aggregation Network)
1、
縮簡訊息路徑和用低層級的準確定位資訊增強特徵金字塔
,建立了
自下而上的路徑增強
2、為了恢復每個建議區域和所有特徵層級之間被破壞的資訊,作者開發了
適應性特徵池化(adaptive feature pooling)技術
,可以將所有特徵層級中的特徵整合到每個建議區域中,避免了任意分配的結果。
3、
全連線融合層
:使用一個小型fc層用於補充mask預測
自下而上的路徑增強
Bottom-up Path Augemtation的提出主要是考慮到網路的淺層特徵對於例項分割非常重要,不難想到淺層特徵中包含大量邊緣形狀等特徵,這對例項分割這種畫素級別的分類任務是起到至關重要的作用的。因此,為了保留更多的淺層特徵,論文引入了Bottom-up Path Augemtation。
紅色的箭頭表示在FPN中,因為要走自底向上的過程,淺層的特徵傳遞到頂層需要經過幾十個甚至上百個網路層,當然這取決於BackBone網路用的什麼,因此經過這麼多層傳遞之後,淺層的特徵資訊丟失就會比較嚴重。
綠色的箭頭表作者添加了一個Bottom-up Path Augemtation結構,這個結構本身不到10層,這樣淺層特徵經過原始FPN中的橫向連線到P2然後再從P2沿著Bottom-up Path Augemtation傳遞到頂層,經過的層數不到10層,能較好的儲存淺層特徵資訊。
注意,這裡的N2和P2表示同一個特徵圖。
但N3,N4,N5和P3,P4,P5不一樣,實際上N3,N4,N5是P3,P4,P5融合後的結果。
Bottom-up Path Augemtation的詳細結構如下圖所示,經過一個尺寸為,步長為的卷積之後,特徵圖尺寸減小為原來的一半然後和這個特徵圖做add操作,得到的結果再經過一個卷積核尺寸為,的卷積層得到。
Bottom-up Path Augemtation詳細結構
適應性特徵池化(adaptive feature pooling)
論文指出,在Faster-RCNN系列的標檢測或分割演算法中,
RPN網路得到的ROI需要經過ROI Pooling或ROI Align提取ROI特徵
,這一步操作中每個ROI所基於的特徵都是
單層特徵
,FPN同樣也是基於單層特徵,因為檢測頭是分別接在每個尺度上的。
本文提出的
Adaptive Feature Pooling
則是
將單層特徵換成多層特徵
,即
每個ROI需要和多層特徵(論文中是4層)做ROI Align的操作,然後將得到的不同層的ROI特徵融合在一起,這樣每個ROI特徵就融合了多層特徵。
RPN網路獲得的每個ROI都要分別和特徵層做ROI Align操作,這樣個ROI就提取到4個不同的特徵圖,然後將4個不同的特徵圖融合在一起就得到最終的特徵,後續的分類和迴歸都是基於此最終的特徵進行。
全連線融合層(Fully-Connected Fusion)
全連線融合層對原有的分割支路(FCN)引入一個
前景二分類的全連線支路,
透過融合這兩條支路的輸出得到更加精確的分割結果。這個模組的具體實現如圖所示。
Fully-Connected Fusion模組
從圖中可以看到這個結構主要是在原始的Mask支路(即帶deconv那條支路)的基礎上增加了下面那個支路做融合。增加的這個支路包含個的卷積層,然後接一個全連線層,再經過reshape操作得到維度和上面支路相同的前背景Mask,即是說下面這個支路做的就是前景和背景的二分類,輸出維度類似於文中說的。而上面的支路輸出維度類似,其中代表資料集目標類別數。最終,這兩條支路的輸出Mask做融合以獲得更加精細的最終結果。
MLFPN
MLFPN來自《
M2det: A single-shot object detector based on multi-level feature pyramid network
》。
之前的特徵金字塔目標檢測網路共有的兩個問題是:
1、原本 backbone 是用於目標分類的網路,導致用於
目標檢測的語義特徵不足;
2、每個用於目標檢測的特徵層主要或者僅僅是由單級特徵層(single-level layers)構成,也就是
僅僅包含了單級資訊
;
這種思想導致一個很嚴重的問題,
對分類子網路來說更深更高的層更容易區分,對定位的迴歸任務來說使用更低更淺的層比較好。
此外,
底層特徵更適合描述具有簡單外觀的目標,而高層特徵更適合描述具有複雜外觀的目標。
在實際中,具有相似大小目標例項的外觀可能非常不同。例如一個交通燈和一個遠距離的人可能具有可以比較的尺寸,但是人的外表更加複雜。因此,
金字塔中的每個特徵圖主要或者僅僅由單層特徵構成可能會導致次優的檢測效能。
為了更好地解決目標檢測中尺度變化帶來的問題,M2det提出一種更有效的
特徵金字塔結構MLFPN
, 其大致流程如下圖所示:首先,對主幹網路提取到的特徵進行融合;然後透過
TUM和FFM提取更有代表性的Multi-level&Mutli-scale特徵
;最後透過
SFAM融合多級特徵
,得到多級特徵金字塔用於最終階段的預測。M2Det使用主幹網路+MLFPN來提取影象特徵,然後採用類似SSD的方式預測密集的包圍框和類別得分,透過NMS得到最後的檢測結果。
如上圖所示,MLFPN主要有3個模組組成:
1)特徵融合模組FFM;
2)細化U型模組TUM;
3)
尺度特徵聚合模組SFAM.
首先, FFMv1對主幹網路提取到的淺層和深層特徵進行融合,得到base feature;
其次,堆疊多個TUM和FFMv2,每個TUM可以產生多個不同scale的feature map,每個FFMv2融合base feature和上一個TUM的輸出,並給到下一個TUM作為輸入(更高level)。
最後,SFAM透過scale-wise拼接和channel-wise attention來聚合multi-level&multi-scale的特徵。
·
特徵融合模組FFM
FFM用於融合M2Det中不同級別的特徵,先透過1x1卷積壓縮通道數,再進行拼接。
FFM1 用於
融合深層和和淺層特徵
,為 MLFPN 提供基本輸入的特徵層(Base Feature);由於 M2Det 使用了 VGG 作為 backbone,因此 FFM1 取出了 Conv4_3 和 Conv5_3 作為輸入:FFMv1
使用兩種不同scale的feature map作為輸入,所以在拼接操作之前加入了上取樣操作來調整大小;
FFMv2用於融合 MLFPN 的基本輸入(Base Feature)和上一個 TUM 模組的輸出,
兩個輸入的scale相同,
所以比較簡單。
·
細化U型模組TUM
TUM使用了比FPN和RetinaNet
更薄的U型網路
。在上取樣和元素相加操作之後
加上1x1卷積來加強學習能力和保持特徵平滑度。
TUM中每個解碼器的輸出共同構成了該TUM的multi-scale輸出。每個TUM的輸出共同構成了multi-level&multi-scale特徵,前面的TUM提供low level feature,後面的TUM提供high level feature。
TUM 的編碼器(encoder)使用 3×3 大小、步長為 2 的卷積層進行特徵提取,特徵圖不斷縮小;解碼器(decoder)同過雙線性插值的方法將特徵圖放大回原大小。
·
尺度特徵聚合模組SFAM
SFAM旨在聚合TUMs產生的多級多尺度特徵,以構造一個
多級特徵金字塔
。在first stage,SFAM沿著channel維度將擁有相同scale的feature map進行拼接,這樣得到的每個scale的特徵都包含了多個level的資訊。然後在second stage,
借鑑SENet的思想,加入channel-wise attention
,以更好地捕捉有用的特徵。SFAM的細節如下圖所示:
網路配置
M2Det的主幹網路採用VGG-16和ResNet-101。
MLFPN的預設配置包含有
8個TUM
,每個TUM包含5個跨步卷積核5個上取樣操作,所以每個TUM的輸出包含了6個不同scale的特徵。
在檢測階段,為6組金字塔特徵每組後面新增兩個卷積層,以分別實現位置迴歸和分類。
後處理階段,使用soft-NMS來過濾無用的包圍框。
上一篇:合財購 大騙局