您當前的位置:首頁 > 攝影

【綜述】神經網路中不同型別的卷積層

作者:由 pprp 發表于 攝影時間:2020-03-14

在計算機視覺中,卷積是最重要的概念之一。同時研究人員也提出了各種新的卷積或者卷積組合來進行改進,其中有的改進是針對速度、有的是為了加深模型、有的是為了對速度和準確率的trade-off。本文將簡單梳理一下卷積神經網路中用到的各種卷積核以及改進版本。文章主要是進行一個梳理,著重講其思路以及作用。

1。 Convolution

2。 1x1/Pointwise Convolutions

3。 Spatial and Cross-Channel Convolutions

4。 Grouped Convolutions

5。 Separable Convolutions

6。 Flattened Convolutions

7。 Shuffled Grouped Convolutions

8。 Dilated Convolution(Atrous Convolution)

9。 Deformable Convolution

10。 Attention

11。 Summary

1. Convolution

下圖是一個單通道卷積操作的示意圖:

【綜述】神經網路中不同型別的卷積層

在深度學習中,卷積的目的是從輸入中提取有用的特徵。在影象處理中,卷積濾波器的選擇範圍非常廣,每種型別的濾波器(比如Sobel運算元、Canny運算元等)都有助於從輸入影象中提取不同的方面或者特徵,比如水平、垂直、邊緣或對角線等特徵。

而在CNN中,不同的特徵是透過卷積在訓練過程中自動學習得到的

filter的權重

得到的。卷積具有

權重共享和平移不變性

的優點。

下圖是一個單filter的卷積的示意圖:

【綜述】神經網路中不同型別的卷積層

多個filter效果就如下圖所示:

【綜述】神經網路中不同型別的卷積層

2. 1x1/Pointwise Convolutions

最初1x1卷積是在Network in Network中提出的,之後1x1convolution最初在GoogLeNet中大量使用,1x1卷積有以下

幾個特點

用於降維或者升維,可以靈活控制特徵圖filter個數

減少引數量,特徵圖filter少了,引數量也會減少。

實現跨通道的互動和資訊整合。

在卷積之後增加了非線性特徵(新增啟用函式)。

【綜述】神經網路中不同型別的卷積層

3. Spatial and Cross-Channel Convolutions

最初被使用在Inception模組中,主要是將跨通道相關性和空間相關性的操作拆分為一系列獨立的操作。

【綜述】神經網路中不同型別的卷積層

先使用1x1 Convolution來約束通道個數,降低計算量,然後每個分支都是用3x3卷積,最終使用concat的方式融合特徵。

pytorch實現(上圖只是簡化圖,和程式碼並不一一對應)

class InceptionA(nn。Module):

def __init__(self, in_channels, pool_features, conv_block=None):

super(InceptionA, self)。__init__()

if conv_block is None:

conv_block = BasicConv2d

self。branch1x1 = conv_block(in_channels, 64, kernel_size=1)

self。branch5x5_1 = conv_block(in_channels, 48, kernel_size=1)

self。branch5x5_2 = conv_block(48, 64, kernel_size=5, padding=2)

self。branch3x3dbl_1 = conv_block(in_channels, 64, kernel_size=1)

self。branch3x3dbl_2 = conv_block(64, 96, kernel_size=3, padding=1)

self。branch3x3dbl_3 = conv_block(96, 96, kernel_size=3, padding=1)

self。branch_pool = conv_block(in_channels, pool_features, kernel_size=1)

def _forward(self, x):

branch1x1 = self。branch1x1(x)

branch5x5 = self。branch5x5_1(x)

branch5x5 = self。branch5x5_2(branch5x5)

branch3x3dbl = self。branch3x3dbl_1(x)

branch3x3dbl = self。branch3x3dbl_2(branch3x3dbl)

branch3x3dbl = self。branch3x3dbl_3(branch3x3dbl)

branch_pool = F。avg_pool2d(x, kernel_size=3, stride=1, padding=1)

branch_pool = self。branch_pool(branch_pool)

outputs = [branch1x1, branch5x5, branch3x3dbl, branch_pool]

return outputs

def forward(self, x):

outputs = self。_forward(x)

return torch。cat(outputs, 1)

4. Grouped Convolutions

組卷積最初是在AlexNet中提出的,之後被大量應用在ResNeXt網路結構中,提出的動機就是透過將feature 劃分為不同的組來降低模型計算複雜度。

下圖詳解了組卷積計算過程。

【綜述】神經網路中不同型別的卷積層

所謂分組就是將輸入feature map的

通道進行分組,然後每個組內部進行卷積操作

,最終將得到的組卷積的結果Concate到一起,得到輸出的feature map。

ResNeXt是ResNet和Inception的結合,其每個分支都採用的相同的拓撲結構。ResNeXt本質是使用組卷積(Grouped Convolutions),透過基數( cardinality )來控制組的數量。

【綜述】神經網路中不同型別的卷積層

使用組卷積的優點:

訓練效率高

。由於卷積被分為幾個不同的組,每個組的計算就可以分配給不同的GPU核心來進行計算。這種結構的設計更符合GPU平行計算的要求,這也能解釋為何ResNeXt在GPU上效率要高於Inception模組。

模型效率高

。模型引數隨著組數或者基數的增加而減少。

效果好

。分組卷積可能能夠比普通卷積組成的模型效果更優,這是因為濾波器之間的關係是稀疏的,而劃分組以後對模型可以起到一定正則化的作用。從COCO資料集榜單就可以看出來,有很多是ResNeXt101作為backbone的模型在排行榜非常靠前的位置。

組卷積為何效果更好的詳細解釋可以看這篇部落格:

https://blog.yani.io/filter-group-tutorial/

,其中有比較詳細的解釋。

5. Separable Convolutions

可分離卷積可以分為

空間可分離卷積

(Spatially Separable Convolutions)和

深度可分離卷積

(depthwise separable convolution)。

假設feature的size為[channel, height , width]

空間也就是指:[height, width]這兩維度組成的。

深度也就是指:channel這一維度。

5.1 Spatially Separable Convolutions

簡單來講,空間可分離卷積就是將原nxn的卷積,分開計算變為1xn和nx1兩步。

下邊舉一個例子:

普通的3x3卷積在一個5x5的feature map上是如下圖這樣進行計算:

【綜述】神經網路中不同型別的卷積層

每個位置需要9次乘法,一共有9個位置,所以整個操作下來就是9x9=81次乘法操作。

如果用空間可分離卷積的話,如下圖所示:

【綜述】神經網路中不同型別的卷積層

第一步先使用3x1的filter,所需計算量為:15x3=45

第二步使用1x3的filter,所需計算量為:9x3=27

總共需要72次乘法就可以得到最終結果,要小於普通卷積的81次乘法。

推廣一下,假設對nxn的feature map使用kernel size為mxm的卷積,

普通卷積需要計算的乘法次數為:

(n-2)\times(n-2)\times m\times m \\

空間可分離卷積需要計算的乘法次數為:

n\times(n-2)\times m+(n-2)\times (n-2)\times m = 2(n-1)(n-2)m \\

那麼代價比為:

\frac{Spatially Separable Convolution}{StandardConvolution}=\frac{2}{m}+\frac{2}{m(n-2)} \\

在n>>m的情況下,

這個比值將變為2/m

,所以可以極大降低計算量。

雖然空間可分離卷積節省了計算成本,但是一般情況很少用到。原因是並非所有的kernel 都可以分為兩個較小的kernel;空間可分離卷積可能會帶來一定的資訊損失;如果將全部的傳統卷積替換為空間可分離卷積,將影響模型的容量, 這樣得到的訓練結果可能是次優的。

5.2 Depthwise Separable Convolutions

深度可分離卷積在Xception或者MobileNet中大量使用,主要有兩個部分組成:

Depthwise Convolution: 獨立地施加在每個通道的空間卷積

Pointwise Convolution: 1x1 convolution,透過深度卷積將通道輸出投影到一個新的通道空間。

下邊是一個深度可分離卷積的pytorch實現:

class DWConv(nn。Module):

def __init__(self, in_plane, out_plane):

super(DWConv, self)。__init__()

self。depth_conv = nn。Conv2d(in_channels=in_plane,

out_channels=in_plane,

kernel_size=3,

stride=1,

padding=1,

groups=in_plane)

self。point_conv = nn。Conv2d(in_channels=in_plane,

out_channels=out_plane,

kernel_size=1,

stride=1,

padding=0,

groups=1)

def forward(self, x):

x = self。depth_conv(x)

x = self。point_conv(x)

return x

透過比對程式碼,很容易理解下圖的操作過程:

【綜述】神經網路中不同型別的卷積層

Inception模組和可分離卷積的區別:

可分離卷積是先用Depthwise Convolution, 然後再使用1x1卷積;Inception中是先使用1x1 Convolution,然後再使用Depthwise Convolution。

深度可分離卷積實現的時候沒有增加非線性特徵(也就是使用啟用函式)。

下面再來比較一下所需計算量:

【綜述】神經網路中不同型別的卷積層

以上圖為例,普通卷積需要的計算量為:

128\times(3\times3\times3)\times(5\times5)=86400 \\

對應128個3x3x3的卷積核移動5x5次的結果。

深度可分離卷積計算量應該分為兩個部分:

第一步:depthwise convolution 有3個3x3x1的kernel移動5x5次。

3\times3\times3\times1\times5\times5=675 \\

第二步:1x1 convolution 有128個1x1x3的kernel移動5x5次。

128\times1\times1\times3\times5\times5=9600 \\

兩步總計10275次乘法,只有普通卷積計算量的12%左右。

推廣一下,對於一個輸入尺寸為[C,H,W]的feature map, 如果用stride=1、padding=0、kernel size=h(h為奇數),那麼輸出的尺寸為

[N_c, H-h+1, W-h+1]

普通卷積需要的乘法次數為:

N_c\times h\times h\times C\times (H-h+1)\times (W-h+1) \\

深度可分離卷積所需要乘法次數為:

DepthConv = C\times h\times h\times 1\times (H-h+1)\times (W-h+1) \\

PointConv = N_c\times 1\times 1\times C\times (H-h+1)\times (W-h+1) \\

DepthwiseSeparableConv=(h\times h+N_c)\times C\times (H-h+1)\times (W-h+1) \\

代價比為:

\frac{DepthwiseSeparableConvolution}{StandardConvolution}=\frac{1}{N_c}+\frac{1}{h^2} \\

在Nc>>h的情況下,

代價比可約等於h的平方分之一。

同樣,深度可分離卷積也有缺點,透過使用深度可分離卷積替代普通的卷積,可以顯著降低模型的計算量,但是與此同時會導致模型的容量也顯著降低。這將導致訓練得到的結果可能也不是最優的。因此,在使用深度可分離卷積的時候要考慮模型容量和計算效率的平衡。

6. Flattened Convolutions

最初在Flattened Convolutional Neural Networks for Feedforward Acceleration中提出,是2015年ICLR的workshop。(連結:

https://

arxiv。org/abs/1412。5474

【綜述】神經網路中不同型別的卷積層

在瞭解了空間可分離卷積以後,再來看Flattened Convolutions就比較簡單了,Flattened Convolution將標準的卷積核拆分成3個1D卷積核(空間可分離卷積只拆分HxW維度),可以極大地降低了計算成本。

論文在結論中提到,使用Flattened Convolutions能夠將計算量減少為原來的10倍,並可以達到類似或更高的準確率在CIFAR-10、CIFAR-100和MNIST資料集中。

深度學習中的學習型濾波器具有分佈特徵值,直接將分離應用在濾波器中會導致嚴重的資訊損失,過多使用的話會對模型準確率產生一定影響。

7. Shuffled Grouped Convolutions

最初是在ShuffleNet中提出的,使用了pointwise group convolution和channel shuffle兩種操作,能夠在保持精度的同時極大地降低計算量。之前解讀的ThunderNet也是在ShuffleNetV2為基礎進行改進的。

Channel Shuffle操作主要是

為了消除原來Grouped Convolution中存在的副作用

,也就是輸出feature map的通道僅僅來自輸入通道的一小部分,因此每個濾波器組僅限於學習一些特定的特性,如下圖(a)所示。

Grouped Convolution的這個屬性會阻礙資訊在通道組之間的資訊流動並削弱了模型的表達。透過使用Channel Shuffle可以

促進通道間資訊的融合

從而解決以上問題。

【綜述】神經網路中不同型別的卷積層

從上圖中,(a)代表的是組卷積,所有輸出只和一部分輸入有關(b)代表的是Channel Shuffle組合的方式,不同的組內部進行了重排,都是用到了輸入的一部分(c)代表的是一種與(b)等價的實現方式。

ShuffleNet還用到了pointwise grouped convolution, 作者認為1x1卷積成本也非常高,所以也對1x1卷積使用組卷積,具體模組化的設計如下圖(b)和(c)所示。

【綜述】神經網路中不同型別的卷積層

所以實際上用到了三種類型的卷積:

shuffled grouped convolution = grouped convolution + Channel Shuffle

pointwise grouped convolution = 1x1 convolution + grouped convolution

depthwise separable convolution

8. Dilated Convolution(Atrous Convolution)

空洞卷積是在DeepLabv1和《Multi-scale context aggregation by dilated convolutions》中提出的。

空洞卷積是在kernel之間插入空洞,並引入了空洞率,普通卷積如下圖(a)所示,其空洞率為1, (b)中所示的Dilated Convolution的空洞率為2,(c)中空洞率為4。

【綜述】神經網路中不同型別的卷積層

上圖中淺綠色的正方形塊代表Dilated Convolution對應的感受野, 顏色越深代表其被

覆蓋

的次數越多。而以上三種方法所需要的計算量是相等的,也就是說,空洞卷積能夠在不增加計算量的情況下,增加模型的感受野。並且如果使用多個空洞卷積組成多層結構來構建網路,有效感受野將呈指數級增長,而所需要的引數數量僅僅呈線性增長。

空洞卷積用於多尺度的上下文資訊,並且不會丟失解析度,在其應用到語義分割模型後,達到了當時的STOA。

不過也存在幾個問題:

Gridding Effect:

【綜述】神經網路中不同型別的卷積層

上圖是具體使用到的結點,可以發現kernel並不連續,並不是所有的點都被

計算

了,這會導致損失資訊的連續性,對細粒度資訊處理(pixel-level dense prediction)來說並不友好。

上下文資訊多少

dilated convolution可以獲取長距離資訊,使用dilated convolution對大物體的效果會有一定效果,但是對小物體來說並不友好,小物體所需要的感受野並不需要太大。所以如何同時處理好不同大小物體之間的關係是使用空洞卷積的關鍵。

9. Deformable Convolution

可變形卷積(DCN) 是一個特別新穎的想法,最初是為了提升目標檢測模型,提出以後也成為刷榜利器。

DCN提出的

動機

是為何特徵提取形狀一定要是正方形或者矩形,為何不能更加自適應的分佈到目標上(如下圖右側所示),進而提出了一種形狀可學習的卷積。

【綜述】神經網路中不同型別的卷積層

實現過程如下圖所示,在普通卷積之外又添加了一個分支,專門用於學習每個點的偏移量,將原始的卷積和offset結合就形成了可變形卷積。

【綜述】神經網路中不同型別的卷積層

10. Attention

這裡介紹兩個最經典的注意力機制的模組,SE Module和CBAM Module。

10.1 Squeeze and Excitation

【綜述】神經網路中不同型別的卷積層

SENet的核心想法是,每個通道的重要性不是一樣的。基於這個想法,SENet添加了一個模組,如上圖靠上的分支,這個模組作用是給每個通道打分,最終將打分的結果與卷積得到的feature map相乘,完成特徵通道的權重重分配。SENet是通道注意力機制的最經典的實現。

pytorch實現:

class SELayer(nn。Module):

def __init__(self, channel, reduction=16):

super(SELayer, self)。__init__()

self。avg_pool = nn。AdaptiveAvgPool2d(1)

self。fc = nn。Sequential(

nn。Linear(channel, channel // reduction, bias=False),

nn。ReLU(inplace=True),

nn。Linear(channel // reduction, channel, bias=False),

nn。Sigmoid()

def forward(self, x):

b, c, _, _ = x。size()

y = self。avg_pool(x)。view(b, c)

y = self。fc(y)。view(b, c, 1, 1)

return x * y。expand_as(x)

其具體實現也非常簡單,值得一提的是,SENet成功拿到了ImageNet2017分類比賽的冠軍。

缺點:不利於並行處理,新增SELayer以後導致在GPU上執行速度有一定的減慢。

10.2 Convolutional Block Attention Module

CBAM模組算是比較早的一批將通道注意力機制和空間注意力機制結合起來的模型,透過新增該模組,能在一定程度上最佳化feature。

CBAM分為Channel Attention Module 和 Spatial Attention Module:

【綜述】神經網路中不同型別的卷積層

pytorch實現通道注意力機制:

class ChannelAttention(nn。Module):

def __init__(self, in_planes, rotio=16):

super(ChannelAttention, self)。__init__()

self。avg_pool = nn。AdaptiveAvgPool2d(1)

self。max_pool = nn。AdaptiveMaxPool2d(1)

self。sharedMLP = nn。Sequential(

nn。Conv2d(in_planes, in_planes // ratio, 1, bias=False), nn。ReLU(),

nn。Conv2d(in_planes // rotio, in_planes, 1, bias=False))

self。sigmoid = nn。Sigmoid()

def forward(self, x):

avgout = self。sharedMLP(self。avg_pool(x))

maxout = self。sharedMLP(self。max_pool(x))

return self。sigmoid(avgout + maxout)

【綜述】神經網路中不同型別的卷積層

pytorch實現空間注意力機制:

class SpatialAttention(nn。Module):

def __init__(self, kernel_size=7):

super(SpatialAttention, self)。__init__()

assert kernel_size in (3,7), “kernel size must be 3 or 7”

padding = 3 if kernel_size == 7 else 1

self。conv = nn。Conv2d(2,1,kernel_size, padding=padding, bias=False)

self。sigmoid = nn。Sigmoid()

def forward(self, x):

avgout = torch。mean(x, dim=1, keepdim=True)

maxout, _ = torch。max(x, dim=1, keepdim=True)

x = torch。cat([avgout, maxout], dim=1)

x = self。conv(x)

return self。sigmoid(x)

最終CBAM模組選擇將兩個部分進行串聯:

【綜述】神經網路中不同型別的卷積層

11. Summary

卷積核的設計非常多,以上僅僅是一部分常見的卷積核,以上卷積核可以這樣分類:

通道和空間

Convolution

1x1 Convolution

Spatial and Cross-Channel Convolutions

通道相關性(channel)

Depthwise Separable Convolutions

Shuffled Grouped Convolutions

Squeeze and Excitation Network

Channel Attention Module in CBAM

空間相關性(HxW)

Spatially Separable Convolutions

Flattened Convolutions

Dilated Convolutions

Deformable Convolution

Spatial Attention Module in CBAM

現在很多CNN模型準確率越來越高,很多研究人員的研究方向也轉向如何在儘可能保證準確率的情況下,儘可能減少模型引數,做好準確率和速度的平衡。

其中ShuffleNet系列效果得到了認可(ShuffleNetV2是騰訊掃一掃專案和ThudnerNet的backbone)。

總結一下效果優異的人工設計的backbone可能會用到以下策略:

單一尺寸卷積核用多個尺寸卷積核代替(參考Inception系列)

使用可變形卷積替代固定尺寸卷積(參考DCN)

大量加入1x1卷積或者pointwise grouped convolution來降低計算量(參考NIN、ShuffleNet)

通道加權處理(參考SENet)

用深度可分離卷積替換普通卷積(參考MobileNet)

使用分組卷積(參考ResNeXt)

分組卷積+channel shuffle(參考shuffleNet)

使用Residual連線(參考ResNet)

【綜述】神經網路中不同型別的卷積層

最後附上一個18年綜述《Benchmark Analysis of RepresentativeDeep Neural Network Architectures》中的圖,文章也提供了程式碼:

https://github.com/CeLuigi/models-comparison.pytorch

致謝:感謝Kunlun Bai,本文中使用了不少便於理解的圖都是出自這位作者。

Reference

標簽: 卷積  self  kernel  nn  __