池化操作(Pooling)是CNN中非常常見的一種操作,Pooling層是模仿人的視覺系統(tǒng)對數(shù)據(jù)進行降維萍歉,池化操作通常也叫做子采樣(Subsampling)或降采樣(Downsampling)喇肋,在構(gòu)建卷積神經(jīng)網(wǎng)絡(luò)時坟乾,往往會用在卷積層之后,通過池化來降低卷積層輸出的特征維度蝶防,有效減少網(wǎng)絡(luò)參數(shù)的同時還可以防止過擬合現(xiàn)象甚侣。
主要功能有以下幾點:
- 抑制噪聲,降低信息冗余
- 提升模型的尺度不變性间学、旋轉(zhuǎn)不變形
- 降低模型計算量
- 防止過擬合
一提到池化操作殷费,大部分人第一想到的就是maxpool和avgpool,實際上還有很多種池化操作低葫。
大部分pooling操作滿足上圖的模型详羡,假設(shè)輸入大小為, 輸出大小為, kernel size簡稱, stride簡稱,滿足以下公式:
1. 最大/平均池化
最大池化就是選擇圖像區(qū)域中最大值作為該區(qū)域池化以后的值嘿悬,反向傳播的時候殷绍,梯度通過前向傳播過程的最大值反向傳播,其他位置梯度為0鹊漠。
使用的時候主到,最大池化又分為重疊池化和非重疊池化茶行,比如常見的stride=kernel size的情況屬于非重疊池化,如果stride<kernel size 則屬于重疊池化登钥。重疊池化相比于非重疊池化不僅可以提升預(yù)測精度畔师,同時在一定程度上可以緩解過擬合。
重疊池化一個應(yīng)用的例子就是yolov3-tiny的backbone最后一層牧牢,使用了一個stride=1, kernel size=2的maxpool進行特征的提取看锉。
>>> import torch
>>> import torch.nn.functional as F
>>> input = torch.Tensor(4,3,16,16)
>>> output = F.max_pool2d(input, kernel_size=2, stride=2)
>>> output.shape
torch.Size([4, 3, 8, 8])
>>>
平均池化就是將選擇的圖像區(qū)域中的平均值作為該區(qū)域池化以后的值。
>>> import torch
>>> import torch.nn.functional as F
>>> input = torch.Tensor(4,3,16,16)
>>> output = F.avg_pool2d(input, kernel_size=2, stride=2)
>>> output.shape
torch.Size([4, 3, 8, 8])
>>>
2. 隨機池化
Stochastic pooling如下圖所示塔鳍,特征區(qū)域的大小越大伯铣,代表其被選擇的概率越高,比如左下角的本應(yīng)該是選擇7轮纫,但是由于引入概率腔寡,5也有一定幾率被選中。
下表是隨機池化在CIFAR-10上的表現(xiàn)掌唾,可以看出放前,使用隨機池化效果和采用dropout的結(jié)果接近,證明了其有一定防止過擬合的作用糯彬。
更詳細內(nèi)容請看論文:《Stochastic Pooling for Regularization of Deep Convolutional Neural Networks》
3. 中值池化
與中值濾波特別相似凭语,但是用的非常少,中值池化也具有學(xué)習(xí)邊緣和紋理結(jié)構(gòu)的特性撩扒,抗噪聲能力比較強似扔。
4. 組合池化
組合池化則是同時利用最大值池化與均值池化兩種的優(yōu)勢而引申的一種池化策略。常見組合策略有兩種:Cat與Add搓谆。常常被當(dāng)做分類任務(wù)的一個trick炒辉,其作用就是豐富特征層,maxpool更關(guān)注重要的局部特征挽拔,而average pooling更關(guān)注全局特征辆脸。
def add_avgmax_pool2d(x, output_size=1):
x_avg = F.adaptive_avg_pool2d(x, output_size)
x_max = F.adaptive_max_pool2d(x, output_size)
return 0.5 * (x_avg + x_max)
def cat_avgmax_pool2d(x, output_size=1):
x_avg = F.adaptive_avg_pool2d(x, output_size)
x_max = F.adaptive_max_pool2d(x, output_size)
return torch.cat([x_avg, x_max], 1)
5. Spatial Pyramid Pooling
SPP是在SPPNet中提出的,SPPNet提出比較早螃诅,在RCNN之后提出的啡氢,用于解決重復(fù)卷積計算和固定輸出的兩個問題,具體方法如下圖所示:
在feature map上通過selective search獲得窗口术裸,然后將這些區(qū)域輸入到CNN中倘是,然后進行分類。
實際上SPP就是多個空間池化的組合袭艺,對不同輸出尺度采用不同的劃窗大小和步長以確保輸出尺度相同搀崭,同時能夠融合金字塔提取出的多種尺度特征,能夠提取更豐富的語義信息。常用于多尺度訓(xùn)練和目標(biāo)檢測中的RPN網(wǎng)絡(luò)瘤睹。
在YOLOv3中有一個網(wǎng)絡(luò)結(jié)構(gòu)叫yolov3-spp.cfg, 這個網(wǎng)絡(luò)往往能達到比yolov3.cfg本身更高的準確率升敲,具體cfg如下:
### SPP ###
[maxpool]
stride=1
size=5
[route]
layers=-2
[maxpool]
stride=1
size=9
[route]
layers=-4
[maxpool]
stride=1
size=13
[route]
layers=-1,-3,-5,-6
### End SPP ###
這里的SPP相當(dāng)于是原來的SPPNet的變體,通過使用多個kernel size的maxpool轰传,最終將所有feature map進行concate驴党,得到新的特征組合。
再來看一下官方提供的yolov3和yolov3-spp在COCO數(shù)據(jù)集上的對比:
可以看到获茬,在幾乎不增加FLOPS的情況下港庄,YOLOv3-SPP要比YOLOv3-608mAP高接近3個百分點。
分析一下SPP有效的原因:
- 從感受野角度來講恕曲,之前計算感受野的時候可以明顯發(fā)現(xiàn)鹏氧,maxpool的操作對感受野的影響非常大,其中主要取決于kernel size大小佩谣。在SPP中把还,使用了kernel size非常大的maxpool會極大提高模型的感受野,筆者沒有詳細計算過darknet53這個backbone的感受野稿存,在COCO上有效很可能是因為backbone的感受野還不夠大笨篷。
- 第二個角度是從Attention的角度考慮瞳秽,這一點啟發(fā)自CSDN@小楞(鏈接在參考文獻中)瓣履,他在文章中這樣講:
出現(xiàn)檢測效果提升的原因:通過spp模塊實現(xiàn)局部特征和全局特征(所以空間金字塔池化結(jié)構(gòu)的最大的池化核要盡可能的接近等于需要池化的featherMap的大小)的featherMap級別的融合练俐,豐富最終特征圖的表達能力袖迎,從而提高MAP。
Attention機制很多都是為了解決遠距離依賴問題腺晾,通過使用kernel size接近特征圖的size可以以比較小的計算代價解決這個問題燕锥。另外就是如果使用了SPP模塊,就沒有必要在SPP后繼續(xù)使用其他空間注意力模塊比如SK block悯蝉,因為他們作用相似归形,可能會有一定冗余。
ps: 這個想法還沒有進行試驗的驗證鼻由,有興趣的可以將YOLOv3-spp中的kernel size改為19暇榴,然后在COCO數(shù)據(jù)集上測試,看是否能夠超越60.6蕉世。
6. Global Average/Max Pooling
Gloabel Average Pooling 是NIN里邊的做法蔼紧,一般使用torchvision提供的預(yù)訓(xùn)練模型進行finetune的時候,通常使用Global Average Pooling狠轻,原因就是可以不考慮圖片的輸入尺寸奸例,只與filter有關(guān)。
>>> import torch
>>> from torch.nn import AdaptiveAvgPool2d
>>> input = torch.zeros((4,12,18,18)) # batch size, fileter, h, w
>>> gap = AdaptiveAvgPool2d(1)
>>> output = gap(input)
>>> output.shape
torch.Size([4, 12, 1, 1])
>>> output.view(input.shape[0],-1).shape
torch.Size([4, 12])
>>>
7. NetVLAD池化
這部分來自:DeepLearning-500-questions#5
NetVLAD是論文《NetVLAD: CNN Architecture for Weakly Supervised Place Recognition》提出的一個局部特征聚合的方法向楼。
在傳統(tǒng)的網(wǎng)絡(luò)里面查吊,例如VGG啊谐区,最后一層卷積層輸出的特征都是類似于Batchsize x 3 x 3 x 512的這種東西,然后會經(jīng)過FC聚合逻卖,或者進行一個Global Average Pooling(NIN里的做法)卢佣,或者怎么樣,變成一個向量型的特征箭阶,然后進行Softmax or 其他的Loss虚茶。
這種方法說簡單點也就是輸入一個圖片或者什么的結(jié)構(gòu)性數(shù)據(jù),然后經(jīng)過特征提取得到一個長度固定的向量仇参,之后可以用度量的方法去進行后續(xù)的操作嘹叫,比如分類啊,檢索啊诈乒,相似度對比等等罩扇。
那么NetVLAD考慮的主要是最后一層卷積層輸出的特征這里,我們不想直接進行欠采樣或者全局映射得到特征怕磨,對于最后一層輸出的W x H x D喂饥,設(shè)計一個新的池化,去聚合一個“局部特征“肠鲫,這即是NetVLAD的作用员帮。
NetVLAD的一個輸入是一個W x H x D的圖像特征,例如VGG-Net最后的3 x 3 x 512這樣的矩陣导饲,在網(wǎng)絡(luò)中還需加一個維度為Batchsize捞高。
NetVLAD還需要另輸入一個標(biāo)量K即表示VLAD的聚類中心數(shù)量,它主要是來構(gòu)成一個矩陣C渣锦,是通過原數(shù)據(jù)算出來的每一個特征的聚類中心硝岗,C的shape即,然后根據(jù)三個輸入袋毙,VLAD是計算下式的V:
其中j表示維度型檀,從1到D,可以看到V的j是和輸入與c對應(yīng)的听盖,對每個類別k胀溺,都對所有的x進行了計算,如果屬于當(dāng)前類別k媳溺,月幌,否則,計算每一個x和它聚類中心的殘差悬蔽,然后把殘差加起來扯躺,即是每個類別k的結(jié)果,最后分別L2正則后拉成一個長向量后再做L2正則,正則非常的重要录语,因為這樣才能統(tǒng)一所有聚類算出來的值倍啥,而殘差和的目的主要是消減不同聚類上的分布不均,兩者共同作用才能得到最后正常的輸出澎埠。
輸入與輸出如下圖所示:
中間得到的K個D維向量即是對D個x都進行了與聚類中心計算殘差和的過程虽缕,最終把K個D維向量合起來后進行即得到最終輸出的長度的一維向量。
而VLAD本身是不可微的蒲稳,因為上面的a要么是0要么是1氮趋,表示要么當(dāng)前描述x是當(dāng)前聚類,要么不是江耀,是個離散的剩胁,NetVLAD為了能夠在深度卷積網(wǎng)絡(luò)里使用反向傳播進行訓(xùn)練,對a進行了修正祥国。
那么問題就是如何重構(gòu)一個a昵观,使其能夠評估當(dāng)前的這個x和各個聚類的關(guān)聯(lián)程度?用softmax來得到:
將這個把上面的a替換后舌稀,即是NetVLAD的公式啊犬,可以進行反向傳播更新參數(shù)。
所以一共有三個可訓(xùn)練參數(shù)壁查,上式a中的觉至,上式a中的,聚類中心潮罪,而原始VLAD只有一個參數(shù)c康谆。
最終池化得到的輸出是一個恒定的K x D的一維向量(經(jīng)過了L2正則)领斥,如果帶Batchsize嫉到,輸出即為Batchsize x (K x D)的二維矩陣。
NetVLAD作為池化層嵌入CNN網(wǎng)絡(luò)即如下圖所示月洛,
原論文中采用將傳統(tǒng)圖像檢索方法VLAD進行改進后應(yīng)用在CNN的池化部分作為一種另類的局部特征池化何恶,在場景檢索上取得了很好的效果。
后續(xù)相繼又提出了ActionVLAD嚼黔、ghostVLAD等改進细层。
評價:這個NetVLAD Layer和SENet非常相似,可以看做是通道注意力機制的實現(xiàn)唬涧,不過具體實現(xiàn)方法有別于SENet疫赎。
8. 雙線性池化
Bilinear Pooling是在《Bilinear CNN Models for Fine-grained Visual Recognition》被提出的,主要用在細粒度分類網(wǎng)絡(luò)中碎节。雙線性池化主要用于特征融合捧搞,對于同一個樣本提取得到的特征x和特征y, 通過雙線性池化來融合兩個特征(外積),進而提高模型分類的能力。
主要思想是對于兩個不同圖像特征的處理方式上的不同胎撇。傳統(tǒng)的介粘,對于圖像的不同特征,我們常用的方法是進行串聯(lián)(連接)晚树,或者進行sum,或者max-pooling姻采。論文的主要思想是,研究發(fā)現(xiàn)人類的大腦發(fā)現(xiàn)爵憎,人類的視覺處理主要有兩個pathway, the ventral stream是進行物體識別的慨亲,the dorsal stream 是為了發(fā)現(xiàn)物體的位置。
論文基于這樣的思想宝鼓,希望能夠?qū)蓚€不同特征進行結(jié)合來共同發(fā)揮作用巡雨,提高細粒度圖像的分類效果。論文希望兩個特征能分別表示圖像的位置和對圖形進行識別席函。論文提出了一種Bilinear Model铐望。
如果特征 x 和特征y來自兩個特征提取器,則被稱為多模雙線性池化(MBP茂附,Multimodal Bilinear Pooling)
如果特征 x = 特征 y正蛙,則被稱為同源雙線性池化(HBP,Homogeneous Bilinear Pooling)或者二階池化(Second-order Pooling)营曼。
pytorch實現(xiàn):
X = torch.reshape(N, D, H * W) # Assume X has shape N*D*H*W
X = torch.bmm(X, torch.transpose(X, 1, 2)) / (H * W) # Bilinear pooling
assert X.size() == (N, D, D)
X = torch.reshape(X, (N, D * D))
X = torch.sign(X) * torch.sqrt(torch.abs(X) + 1e-5) # Signed-sqrt normalization
X = torch.nn.functional.normalize(X) # L2 normalization
之后又有很多人出于對雙線性池化存在的特征維度過高等問題進行各種改進乒验,具體可以看知乎文章:
https://zhuanlan.zhihu.com/p/62532887
9. UnPooling
是一種上采樣操作,具體操作如下:
流程描述:
1.在Pooling(一般是Max Pooling)時蒂阱,保存最大值的位置锻全。
2.中間經(jīng)歷若干網(wǎng)絡(luò)層的運算。
3.上采樣階段录煤,利用第1步保存的Max Location鳄厌,重建下一層的feature map。
UnPooling不完全是Pooling的逆運算妈踊,Pooling之后的feature map了嚎,要經(jīng)過若干運算,才會進行UnPooling操作廊营;對于非Max Location的地方以零填充歪泳。然而這樣并不能完全還原信息。
10. 參考
https://arxiv.org/pdf/1603.07285.pdf
https://arxiv.org/abs/1301.3557
https://zhuanlan.zhihu.com/p/77040467
https://arxiv.org/pdf/1611.05138.pdf
https://blog.csdn.net/qq_33270279/article/details/103898245
https://github.com/scutan90/DeepLearning-500-questions