真正的即插即用!盤(pán)點(diǎn)11種CNN網(wǎng)絡(luò)設(shè)計(jì)中精巧通用的“小”插件

前言

本文盤(pán)點(diǎn)一些CNN網(wǎng)絡(luò)中設(shè)計(jì)比較精巧而又實(shí)用的“插件”。所謂“插件”,就是不改變網(wǎng)絡(luò)主體結(jié)構(gòu), 可以很容易嵌入到主流網(wǎng)絡(luò)當(dāng)中,提高網(wǎng)絡(luò)提取特征的能力,能夠做到plug-and-play。網(wǎng)絡(luò)也有很多類(lèi)似盤(pán)點(diǎn)工作,都宣稱(chēng)所謂的即插即用、無(wú)痛漲點(diǎn)。不過(guò)根據(jù)筆者經(jīng)驗(yàn)和收集,發(fā)現(xiàn)很多插件都是不實(shí)用、不通用、甚至不work的,于是有了這一篇。

首先,我的認(rèn)識(shí)是:既然是“插件”,就要是錦上添花的,又容易植入,容易落地的,真正的即插即用。本文盤(pán)點(diǎn)的“插件”,在很多SOTA網(wǎng)絡(luò)中會(huì)看到它們的影子。是值得推廣的良心“插件”,真正能做到plug-and-play。總之一句話,就是能夠work的“插件”。很多“插件”都為提升CNN能力而推出的,例如平移、旋轉(zhuǎn)、scale等變性能力,多尺度特征提取能力,感受野等能力,感知空間位置能力等等。

入圍名單:STN、ASPP、Non-local、SE、CBAM、DCNv1&v2、CoordConv、Ghost、BlurPool、RFB、ASFF

1 STN

出自論文:Spatial Transformer Networks

論文鏈接:https://arxiv.org/pdf/1506.02025.pdf

核心解析

在OCR等任務(wù)中,你會(huì)經(jīng)??吹剿纳碛啊?duì)于CNN網(wǎng)絡(luò),我們希望其具有對(duì)物體的姿態(tài)、位置等有一定的不變性。即在測(cè)試集上可以適應(yīng)一定的姿態(tài)、位置的變化。不變性或等變性可以有效提高模型泛化能力。雖然CNN使用sliding-window卷積操作,在一定程度上具有平移不變性。但很多研究發(fā)現(xiàn),下采樣會(huì)破壞網(wǎng)絡(luò)的平移不變性。所以可以認(rèn)為網(wǎng)絡(luò)的不變性能力非常弱,更不用說(shuō)旋轉(zhuǎn)、尺度、光照等不變性。一般我們利用數(shù)據(jù)增強(qiáng)來(lái)實(shí)現(xiàn)網(wǎng)絡(luò)的“不變性”。

本文提出STN模塊,顯式將空間變換植入到網(wǎng)絡(luò)當(dāng)中,進(jìn)而提高網(wǎng)絡(luò)的旋轉(zhuǎn)、平移、尺度等不變性??梢岳斫鉃椤皩?duì)齊”操作。STN的結(jié)構(gòu)如上圖所示,每一個(gè)STN模塊由Localisation net,Grid generator和Sampler三部分組成。Localisation net用于學(xué)習(xí)獲取空間變換的參數(shù),就是上式中的六個(gè)參數(shù)。Grid generator用于坐標(biāo)映射。Sampler用于像素的采集,是利用雙線性插值的方式進(jìn)行。

STN的意義是能夠把原始的圖像糾正成為網(wǎng)絡(luò)想要的理想圖像,并且該過(guò)程為無(wú)監(jiān)督的方式進(jìn)行,也就是變換參數(shù)是自發(fā)學(xué)習(xí)獲取的,不需要標(biāo)注信息。該模塊是一個(gè)獨(dú)立模塊,可以在CNN的任何位置插入。符合本次“插件”的盤(pán)點(diǎn)要求。

核心代碼:

classSpatialTransformer(nn.Module):def__init__(self, spatial_dims):super(SpatialTransformer,self).__init__()self._h,self._w = spatial_dimsself.fc1 = nn.Linear(32*4*4,1024)# 可根據(jù)自己的網(wǎng)絡(luò)參數(shù)具體設(shè)置self.fc2 = nn.Linear(1024,6)defforward(self, x):batch_images = x#保存一份原始數(shù)據(jù)x = x.view(-1,32*4*4)# 利用FC結(jié)構(gòu)學(xué)習(xí)到6個(gè)參數(shù)x =self.fc1(x)x =self.fc2(x)x = x.view(-1,2,3)# 2x3# 利用affine_grid生成采樣點(diǎn)affine_grid_points = F.affine_grid(x, torch.Size((x.size(0),self._in_ch,self._h,self._w)))# 將采樣點(diǎn)作用到原始數(shù)據(jù)上? ? ? ? rois = F.grid_sample(batch_images, affine_grid_points)returnrois, affine_grid_points

2 ASPP

插件全稱(chēng):atrous spatial pyramid pooling

出自論文:DeepLab: Semantic Image Segmentation with Deep Convolutional Nets, Atrous Conv

論文鏈接:https://arxiv.org/pdf/1606.00915.pdf

核心解析

本插件是帶有空洞卷積的空間金字塔池化模塊,主要是為了提高網(wǎng)絡(luò)的感受野,并引入多尺度信息而提出的。我們知道,對(duì)于語(yǔ)義分割網(wǎng)絡(luò),通常面臨是分辨率較大的圖片,這就要求我們的網(wǎng)絡(luò)有足夠的感受野來(lái)覆蓋到目標(biāo)物體。對(duì)于CNN網(wǎng)絡(luò)基本是靠卷積層的堆疊加上下采樣操作來(lái)獲取感受野的。本文的該模塊可以在不改變特征圖大小的同時(shí)控制感受野,這有利于提取多尺度信息。其中rate控制著感受野的大小,r越大感受野越大。

ASPP主要包含以下幾個(gè)部分:1. 一個(gè)全局平均池化層得到image-level特征,并進(jìn)行1X1卷積,并雙線性插值到原始大小;2. 一個(gè)1X1卷積層,以及三個(gè)3X3的空洞卷積;3. 將5個(gè)不同尺度的特征在channel維度concat在一起,然后送入1X1的卷積進(jìn)行融合輸出。

核心代碼

classASPP(nn.Module):def__init__(self, in_channel=512, depth=256):super(ASPP,self).__init__()self.mean = nn.AdaptiveAvgPool2d((1,1))self.conv = nn.Conv2d(in_channel, depth,1,1)self.atrous_block1 = nn.Conv2d(in_channel, depth,1,1)# 不同空洞率的卷積self.atrous_block6 = nn.Conv2d(in_channel, depth,3,1, padding=6, dilation=6)self.atrous_block12 = nn.Conv2d(in_channel, depth,3,1, padding=12, dilation=12)self.atrous_block18 = nn.Conv2d(in_channel, depth,3,1, padding=18, dilation=18)self.conv_1x1_output = nn.Conv2d(depth *5, depth,1,1)defforward(self, x):size = x.shape[2:]# 池化分支image_features =self.mean(x)image_features =self.conv(image_features)image_features = F.upsample(image_features, size=size, mode='bilinear')# 不同空洞率的卷積atrous_block1 =self.atrous_block1(x)atrous_block6 =self.atrous_block6(x)atrous_block12 =self.atrous_block12(x)atrous_block18 =self.atrous_block18(x)# 匯合所有尺度的特征x = torch.cat([image_features, atrous_block1, atrous_block6,atrous_block12, atrous_block18], dim=1)# 利用1X1卷積融合特征輸出x =self.conv_1x1_output(x)returnnet

3 Non-local

出自論文:Non-local Neural Networks

論文鏈接:https://arxiv.org/abs/1711.07971

核心解析

Non-Local是一種attention機(jī)制,也是一個(gè)易于植入和集成的模塊。Local主要是針對(duì)感受野(receptive field)來(lái)說(shuō)的,以CNN中的卷積操作和池化操作為例,它的感受野大小就是卷積核大小,而我們常用3X3的卷積層進(jìn)行堆疊,它只考慮局部區(qū)域,都是local的運(yùn)算。不同的是,non-local操作感受野可以很大,可以是全局區(qū)域,而不是一個(gè)局部區(qū)域。捕獲長(zhǎng)距離依賴(lài)(long-range dependencies),即如何建立圖像上兩個(gè)有一定距離的像素之間的聯(lián)系,是一種注意力機(jī)制。所謂注意力機(jī)制就是利用網(wǎng)絡(luò)生成saliency map,注意力對(duì)應(yīng)的是顯著性區(qū)域,是需要網(wǎng)絡(luò)重點(diǎn)關(guān)注的區(qū)域。

首先分別對(duì)輸入的特征圖進(jìn)行 1X1的卷積來(lái)壓縮通道數(shù),得到,特征。

通過(guò)reshape操作,轉(zhuǎn)化三個(gè)特征的維度,然后對(duì)進(jìn)行矩陣乘操作,得到類(lèi)似協(xié)方差矩陣, 這一步為了計(jì)算出特征中的自相關(guān)性,即得到每幀中每個(gè)像素對(duì)其他所有幀所有像素的關(guān)系。

然后對(duì)自相關(guān)特征進(jìn)行 Softmax 操作,得到0~1的weights,這里就是我們需要的 Self-attention系數(shù)。

最后將 attention系數(shù),對(duì)應(yīng)乘回特征矩陣g上,與原輸入 feature map X 殘差相加輸出即可。

這里我們結(jié)合一個(gè)簡(jiǎn)單例子理解一下,假設(shè)g為(我們暫時(shí)不考慮batch和channel維度):

g = torch.tensor([[1,2],[3, 4]).view(-1,1).float()

為:

theta= torch.tensor([2,4,6,8]).view(-1,1)

為:

phi= torch.tensor([7,5,3,1]).view(1, -1)

那么,和矩陣相乘如下:

tensor([[14., 10.,? 6.,? 2.],[28., 20., 12.,? 4.],[42., 30., 18.,? 6.],[56., 40., 24.,? 8.]])

進(jìn)過(guò)softmax(dim=-1)后如下,每一行代表著g里面的元素的重要程度,每一行前面的值比較大,因此希望多“注意”到g前面的元素,也就是1比較重要一點(diǎn)?;蛘哌@樣理解:注意力矩陣代表著g中每個(gè)元素和其他元素的依賴(lài)程度。

tensor([[9.8168e-01, 1.7980e-02, 3.2932e-04, 6.0317e-06],[9.9966e-01, 3.3535e-04, 1.1250e-07, 3.7739e-11],[9.9999e-01, 6.1442e-06, 3.7751e-11, 2.3195e-16],[1.0000e+00, 1.1254e-07, 1.2664e-14, 1.4252e-21]])

注意力作用上之后,整體值向原始g中的值都向1靠攏:

tensor([[1.0187, 1.0003],[1.0000, 1.0000]])

核心代碼

classNonLocal(nn.Module):def __init__(self, channel):super(NonLocalBlock,self).__init__()self.inter_channel = channel// 2self.conv_phi = nn.Conv2d(channel,self.inter_channel,1,1,0, False)self.conv_theta = nn.Conv2d(channel,self.inter_channel,1,1,0, False)self.conv_g = nn.Conv2d(channel,self.inter_channel,1,1,0, False)self.softmax = nn.Softmax(dim=1)self.conv_mask = nn.Conv2d(self.inter_channel, channel,1,1,0, False)def forward(self, x):# [N, C, H , W]? ? ? ? b, c, h, w = x.size()# 獲取phi特征,維度為[N, C/2, H * W],注意是要保留batch和通道維度的,是在HW上進(jìn)行的x_phi =self.conv_phi(x).view(b, c,-1)# 獲取theta特征,維度為[N, H * W, C/2]x_theta =self.conv_theta(x).view(b, c,-1).permute(0,2,1).contiguous()# 獲取g特征,維度為[N, H * W, C/2]x_g =self.conv_g(x).view(b, c,-1).permute(0,2,1).contiguous()# 對(duì)phi和theta進(jìn)行矩陣乘,[N, H * W, H * W]? ? ? ? mul_theta_phi = torch.matmul(x_theta, x_phi)# softmax拉到0~1之間mul_theta_phi =self.softmax(mul_theta_phi)# 與g特征進(jìn)行矩陣乘運(yùn)算,[N, H * W, C/2]? ? ? ? mul_theta_phi_g = torch.matmul(mul_theta_phi, x_g)# [N, C/2, H, W]mul_theta_phi_g = mul_theta_phi_g.permute(0,2,1).contiguous().view(b,self.inter_channel, h, w)# 1X1卷積擴(kuò)充通道數(shù)mask =self.conv_mask(mul_theta_phi_g)out= mask + x# 殘差連接returnout

4 SE

出自論文:Squeeze-and-Excitation Networks

論文鏈接:https://arxiv.org/pdf/1709.01507.pdf

核心解析

本文是ImageNet最后一屆比賽的冠軍作品,你會(huì)在很多經(jīng)典網(wǎng)絡(luò)結(jié)構(gòu)中看到它的身影,例如Mobilenet v3。其實(shí)是一種通道注意力機(jī)制。由于特征壓縮和FC的存在,其捕獲的通道注意力特征是具有全局信息的。本文提出了一種新的結(jié)構(gòu)單元——“Squeeze-and Excitation(SE)”模塊,可以自適應(yīng)的調(diào)整各通道的特征響應(yīng)值,對(duì)通道間的內(nèi)部依賴(lài)關(guān)系進(jìn)行建模。有以下幾個(gè)步驟:

Squeeze: 沿著空間維度進(jìn)行特征壓縮,將每個(gè)二維的特征通道變成一個(gè)數(shù),是具有全局的感受野。

Excitation: 每個(gè)特征通道生成一個(gè)權(quán)重,用來(lái)代表該特征通道的重要程度。

Reweight:將Excitation輸出的權(quán)重看做每個(gè)特征通道的重要性,通過(guò)相乘的方式作用于每一個(gè)通道上。

核心代碼

classSE_Block(nn.Module):def__init__(self, ch_in, reduction=16):? ? ? ? super(SE_Block, self).__init__()self.avg_pool = nn.AdaptiveAvgPool2d(1)# 全局自適應(yīng)池化? ? ? ? self.fc = nn.Sequential(nn.Linear(ch_in, ch_in // reduction, bias=False),nn.ReLU(inplace=True),nn.Linear(ch_in // reduction, ch_in, bias=False),? ? ? ? ? ? nn.Sigmoid()? ? ? ? )defforward(self, x):? ? ? ? b, c, _, _ = x.size()y = self.avg_pool(x).view(b, c)# squeeze操作y = self.fc(y).view(b, c,1,1)# FC獲取通道注意力權(quán)重,是具有全局信息的returnx * y.expand_as(x)# 注意力作用每一個(gè)通道上

5 CBAM

出自論文:CBAM: Convolutional Block Attention Module

論文鏈接:https://openaccess.thecvf.com/content_ECCV_2018/papers/Sanghyun_Woo_Convolutional_Block_Attention_ECCV_2018_paper.pdf

核心解析

SENet在feature map的通道上進(jìn)行attention權(quán)重獲取,然后與原來(lái)的feature map相乘。這篇文章指出,該種attention方法法只關(guān)注了通道層面上哪些層會(huì)具有更強(qiáng)的反饋能力,但是在空間維度上并不能體現(xiàn)出attention。CBAM作為本文的亮點(diǎn),將attention同時(shí)運(yùn)用在channel和spatial兩個(gè)維度上, CBAM與SE Module一樣,可以嵌入在大部分的主流網(wǎng)絡(luò)中,在不顯著增加計(jì)算量和參數(shù)量的前提下能提升模型的特征提取能力。

通道注意力: 如上圖所示,輸入是一個(gè) H×W×C 的特征F,我們先分別進(jìn)兩個(gè)空間的全局平均池化和最大池化得到 兩個(gè) 1×1×C 的通道描述。再將它們分別送進(jìn)一個(gè)兩層的神經(jīng)網(wǎng)絡(luò),第一層神經(jīng)元個(gè)數(shù)為 C/r,激活函數(shù)為 Relu,第二層神經(jīng)元個(gè)數(shù)為 C。注意,這個(gè)兩層的神經(jīng)網(wǎng)絡(luò)是共享的。然后,再將得到的兩個(gè)特征相加后經(jīng)過(guò)一個(gè) Sigmoid 激活函數(shù)得到權(quán)重系數(shù) Mc。最后,拿權(quán)重系數(shù)和 原來(lái)的特征 F 相乘即可得到縮放后的新特征。偽代碼:

defforward(self, x):# 利用FC獲取全局信息,和Non-local的矩陣相乘本質(zhì)上式一樣的avg_out =self.fc2(self.relu1(self.fc1(self.avg_pool(x))))max_out =self.fc2(self.relu1(self.fc1(self.max_pool(x))))? ? out = avg_out + max_outreturnself.sigmoid(out)

空間注意力: 與通道注意力相似,給定一個(gè) H×W×C 的特征 F‘,我們先分別進(jìn)行一個(gè)通道維度的平均池化和最大池化得到兩個(gè) H×W×1 的通道描述,并將這兩個(gè)描述按照通道拼接在一起。然后,經(jīng)過(guò)一個(gè) 7×7 的卷積層, 激活函數(shù)為 Sigmoid,得到權(quán)重系數(shù) Ms。最后,拿權(quán)重系數(shù)和特征 F’ 相乘即可得到縮放后的新特征。偽代碼:

defforward(self, x):# 這里利用池化獲取全局信息avg_out = torch.mean(x, dim=1, keepdim=True)max_out,_= torch.max(x, dim=1, keepdim=True)x = torch.cat([avg_out, max_out], dim=1)x =self.conv1(x)returnself.sigmoid(x)

6 DCN v1&v2

插件全稱(chēng):Deformable Convolutional

出自論文

v1: [Deformable Convolutional Networks]

https://arxiv.org/pdf/1703.06211.pdf

v2: [Deformable ConvNets v2: More Deformable, Better Results]

https://arxiv.org/pdf/1811.11168.pdf

核心解析

變形卷積可以看作變形+卷積兩個(gè)部分,因此可以當(dāng)作插件使用。在各大主流檢測(cè)網(wǎng)絡(luò)中,變形卷積真是漲點(diǎn)神器,網(wǎng)上解讀也非常之多。和傳統(tǒng)的固定窗口的卷積相比,變形卷積可以有效地對(duì)幾何圖形,因?yàn)樗摹熬植扛惺芤啊笔强蓪W(xué)習(xí)的,面向全圖的。這篇論文同時(shí)提出了deformable ROI pooling,這兩個(gè)方法都是增加額外偏移量的空間采樣位置,不需要額外的監(jiān)督,是自監(jiān)督的過(guò)程。

如上圖所示,a為不同的卷積,b為變形卷積,深色的點(diǎn)為卷積核實(shí)際采樣的位置,和“標(biāo)準(zhǔn)的”位置有一定的偏移。c和d為變形卷積的特殊形式,其中c為我們常見(jiàn)到的空洞卷積,d為具有學(xué)習(xí)旋轉(zhuǎn)特性的卷積,也具備提升感受野的能力。

變形卷積和STN過(guò)程非常類(lèi)似,STN是利用網(wǎng)絡(luò)學(xué)習(xí)出空間變換的6個(gè)參數(shù),對(duì)特征圖進(jìn)行整體變換,旨在增加網(wǎng)絡(luò)對(duì)形變的提取能力。DCN是利用網(wǎng)絡(luò)學(xué)習(xí)數(shù)整圖offset,比STN的變形更“全面一點(diǎn)”。STN是仿射變換,DCN是任意變換。公式不貼了,可以直接看代碼實(shí)現(xiàn)過(guò)程。

變形卷積具有V1和V2兩個(gè)版本,其中V2是在V2的基礎(chǔ)上進(jìn)行改進(jìn),除了采樣offset,還增加了采樣權(quán)重。V2認(rèn)為3X3采樣點(diǎn)也應(yīng)該具有不同的重要程度,因此該處理方法更具有靈活性和擬合能力。

核心代碼

defforward(self, x):# 學(xué)習(xí)出offset,包括x和y兩個(gè)方向,注意是每一個(gè)channel中的每一個(gè)像素都有一個(gè)x和y的offsetoffset =self.p_conv(x)ifself.v2:# V2的時(shí)候還會(huì)額外學(xué)習(xí)一個(gè)權(quán)重系數(shù),經(jīng)過(guò)sigmoid拉到0和1之間m = torch.sigmoid(self.m_conv(x))# 利用offset對(duì)x進(jìn)行插值,獲取偏移后的x_offsetx_offset =self.interpolate(x,offset)ifself.v2:# V2的時(shí)候,將權(quán)重系數(shù)作用到特征圖上m = m.contiguous().permute(0,2,3,1)m = m.unsqueeze(dim=1)m = torch.cat([mfor_inrange(x_offset.size(1))], dim=1)? ? ? ? x_offset *= mout =self.conv(x_offset)# offset作用后,在進(jìn)行標(biāo)準(zhǔn)的卷積過(guò)程returnout

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容