網(wǎng)站建設 后臺北京谷歌seo
1 深度學習池化概述
1.1 什么是池化
池化層是卷積神經(jīng)網(wǎng)絡中常用的一個組件,池化層經(jīng)常用在卷積層后邊,通過池化來降低卷積層輸出的特征向量,避免出現(xiàn)過擬合的情況。池化的基本思想就是對不同位置的特征進行聚合統(tǒng)計。池化層主要是模仿人的視覺系統(tǒng)對數(shù)據(jù)進行降維,用更高層次的特征表示圖像。池化層一般沒有參數(shù),所以反向傳播的時候,只需對輸入?yún)?shù)求導,不需要進行權值更新。
池化操作的基本思想是將特征圖劃分為若干個子區(qū)域(一般為矩形),并對每個子區(qū)域進行統(tǒng)計匯總。池化操作的方式可以有很多種,比如最大池化(Max Pooling)、平均池化(Average Pooling)等。其中,最大池化操作會選取每個子區(qū)域內(nèi)的最大值作為輸出,而平均池化操作則會計算每個子區(qū)域內(nèi)的平均值作為輸出。
1.2 池化的作用
理論上來說,網(wǎng)絡可以在不對原始輸入圖像執(zhí)行降采樣的操作,通過堆疊多個的卷積層來構建深度神經(jīng)網(wǎng)絡,如此一來便可以在保留更多空間細節(jié)信息的同時提取到更具有判別力的抽象特征。然而,考慮到計算機的算力瓶頸,通常都會引入池化層,來進一步地降低網(wǎng)絡整體的計算代價,這是引入池化層最根本的目的。
池化層大大降低了網(wǎng)絡模型參數(shù)和計算成本,也在一定程度上降低了網(wǎng)絡過擬合的風險。概括來說,池化層主要有以下五點作用:
-
增大網(wǎng)絡感受野
-
抑制噪聲,降低信息冗余
-
降低模型計算量,降低網(wǎng)絡優(yōu)化難度,防止網(wǎng)絡過擬合
-
使模型對輸入圖像中的特征位置變化更加魯棒
1.3 池化核大小
池化窗口的大小,在PyTorch里池化核大小可以是一個整數(shù)或者一個元組,例如 kernel_size=2 或者 kernel_size=(2, 3)。
- 如果是一個整數(shù),則表示高和寬方向上的池化窗口大小相同;
- 如果是一個元組,則第一個元素表示高方向上的池化窗口大小,第二個元素表示寬方向上的池化窗口大小。
1.4 步幅大小
用于指定池化窗口在高和寬方向上的步幅大小,可以是一個整數(shù)或者一個元組,例如 stride=2 或者 stride=(2, 3)。
- 如果是一個整數(shù),則表示高和寬方向上的步幅大小相同;
- 如果是一個元組,則第一個元素表示高方向上的步幅大小,第二個元素表示寬方向上的步幅大小。
1.5 填充
池化層的填充(padding)可以控制池化操作在特征圖邊緣的行為,使得池化后的輸出特征圖與輸入特征圖大小相同或相近。
在池化操作時,如果輸入特征圖的尺寸不能被池化窗口的大小整除,那么最后一列或者最后一行的部分像素就無法被包含在池化窗口中進行池化,因此池化后的輸出特征圖尺寸會減小。
通過在輸入特征圖的邊緣添加填充,可以使得池化操作在邊緣像素處進行池化,避免了信息的丟失,并且保持了輸出特征圖的大小與輸入特征圖相同或相近。同時,填充也可以增加模型的穩(wěn)定性,減少過擬合的風險。
需要注意的是,池化層的填充和卷積層的填充有所不同:
- 池化層的填充通常是指在輸入特征圖的邊緣添加0值像素;
- 卷積層的填充是指在輸入特征圖的邊緣添加0值像素或者復制邊緣像素。
PyTorch里的填充大小可以是一個整數(shù)或者一個元組,例如 padding=1 或者 padding=(1, 2)。
- 如果是一個整數(shù),則表示在高和寬方向上的填充大小相同;
- 如果是一個元組,則第一個元素表示高方向上的填充大小,第二個元素表示寬方向上的填充大小。默認為 0,表示不進行填充。
2 pytorch中的池化詳解
2.1 Max Pooling(最大池化)
2.1.1 定義
最大池化(Max Pooling)是將輸入的圖像劃分為若干個矩形區(qū)域,對每個子區(qū)域輸出最大值。其定義如下:
最大池化就是選取圖像區(qū)域中的最大值作為該區(qū)域池化后的值。在前向傳播過程中,選擇圖像區(qū)域中的最大值作為該區(qū)域池化后的值;在反向傳播過程中,梯度通過前向傳播過程時的最大值反向傳播,其他位置的梯度為0。如下圖所示,采用22的filters,步長stride=2,在原特征圖44中提取特征得到右圖2*2。
最大值池化的優(yōu)點在于它能學習到圖像的邊緣和紋理結構。
對于最大池化,在前向傳播計算時,是選取的每個區(qū)域中的最大值,這里需要記錄下最大值在每個小區(qū)域中的位置。在反向傳播時,只有那個最大值對下一層有貢獻,所以將殘差傳遞到該最大值的位置,區(qū)域內(nèi)其余位置置零。具體過程如下圖,其中4*4矩陣中非零的位置即為前邊計算出來的每個小區(qū)域的最大值的位置。
2.1.2 pytorch中的最大池化
PyTorch中的最大池化函數(shù):
torch.nn.MaxPool2d(kernel_size, stride=None, padding=0, dilation=1, return_indices=False, ceil_mode=False)
-
kernel_size (int or tuple)【必選】:max pooling 的窗口大小,當最大池化窗口是方形的時候,只需要一個整數(shù)邊長即可;最大池化窗口不是方形時,要輸入一個元組表 高和寬。
-
stride (int or tuple, optional)【可選】:max pooling 的窗口移動的步長。默認值是 kernel_size
-
padding (int or tuple, optional)【可選】:輸入的每一條邊補充0的層數(shù)
-
dilation (int or tuple, optional)【可選】:一個控制窗口中元素步幅的參數(shù)
-
return_indices (bool)【可選】:如果等于 True,會返回輸出最大值的序號,對于上采樣操作會有幫助
-
ceil_mode (bool)【可選】:如果等于True,計算輸出信號大小的時候,會使用向上取整,代替默認的向下取整的操作
torch.nn.MaxPool2d
和 torch.nn.functional.max_pool2d
,在 pytorch 構建模型中,都可以作為最大池化層的引入,但前者為類模塊,后者為函數(shù),在使用上存在不同。
torch.nn.functional.max_pool2d(input, kernel_size, stride=None, padding=0, dilation=1, ceil_mode=False, return_indices=False
)
2.1.3 使用示例
- 張量池化
import torch# 定義輸入數(shù)據(jù)張量,大小為 (batch_size, channels, height, width)
input_tensor = torch.randn(2, 3, 16, 16)# 定義最大池化層,kernel_size 為池化核大小,stride 為步幅
max_pool = torch.nn.MaxPool2d(kernel_size=2, stride=2)# 對輸入數(shù)據(jù)進行最大池化操作
output_tensor = max_pool(input_tensor)# 輸出池化前后的結果張量大小
print("input_tensor:", input_tensor.shape)
print("output_tensor:", output_tensor.shape)
運行結果顯示:
input_tensor: torch.Size([2, 3, 16, 16])
output_tensor: torch.Size([2, 3, 8, 8])
輸入大小為 (2,3,16,16)的張量, 然后定義了一個最大池化層,池化操作以后,
最后輸出的張量大小是: torch.Size([2, 3, 8, 8])
- 圖片池化
import torch
from PIL import Image
from torchvision.transforms import ToTensor
from torchvision.transforms.functional import to_pil_image
import matplotlib.pyplot as plt# 讀入示例圖片并將其轉(zhuǎn)換為 PyTorch 張量
img = Image.open('./data/lena.jpeg')
img_tensor = ToTensor()(img)# 定義 MaxPool2d 函數(shù),進行池化操作
max_pool = torch.nn.MaxPool2d(kernel_size=2, stride=2)
img_pool = max_pool(img_tensor.unsqueeze(0)).squeeze(0)# 將池化后的張量轉(zhuǎn)換為 PIL 圖像并保存
img_pool_pil = to_pil_image(img_pool)plt.subplot(121)
plt.imshow(img)
plt.title('original')
plt.axis('off')
plt.subplot(122)
plt.imshow(img_pool_pil)
plt.title('pool')
plt.axis('off')
plt.show()
運行結果顯示:
2.1.4 總結
對于最大池化操作,只選擇每個矩形區(qū)域中的最大值進入下一層,而其他元素將不會進入下一層。所以最大池化提取特征圖中響應最強烈的部分進入下一層,這種方式摒棄了網(wǎng)絡中大量的冗余信息,使得網(wǎng)絡更容易被優(yōu)化。同時這種操作方式也常常丟失了一些特征圖中的細節(jié)信息,所以最大池化更多保留些圖像的紋理信息。
2.2 Average Pooling(平均池化)
2.2.1 定義
平均池化(Average Pooling)是將輸入的圖像劃分為若干個矩形區(qū)域,對每個子區(qū)域輸出所有元素的平均值。其定義如下:
平均池化就是計算圖像區(qū)域的平均值作為該區(qū)域池化后的值,Resnet網(wǎng)絡結構后一般會使用平均池化。
對于平均池化,我們需要把殘差平分,傳遞到前邊小區(qū)域的n個單元即可,不需要記錄下元素在每個小區(qū)域中的位置。平均池化比較容易讓人理解錯的地方就是會簡單的認為直接把梯度復制N遍之后直接反向傳播回去,但是這樣會造成loss之和變?yōu)樵瓉淼腘倍,網(wǎng)絡是會產(chǎn)生梯度爆炸的。
2.2.2 pytorch中的平均池化
torch.nn.AvgPool2d(kernel_size, stride=None, padding=0, ceil_mode=False, count_include_pad=True, divisor_override=None)
-
kernel_size:池化窗口的大小??梢允且粋€整數(shù),表示正方形窗口的邊長,也可以是一個元組,表示不同維度的窗口大小。例如,(2, 2)表示寬和高為2的正方形窗口。
-
stride:池化窗口的步幅??梢允且粋€整數(shù),表示在所有維度上的步幅相同,也可以是一個元組,表示不同維度上的步幅。例如,(2, 2)表示在寬和高上的步幅為2。
-
padding:輸入張量的填充大小??梢允且粋€整數(shù),表示在所有維度上的填充大小相同,也可以是一個元組,表示不同維度上的填充大小。例如,(1, 1)表示在寬和高上的填充大小為1。
-
ceil_mode:是否采用向上取整的方式計算輸出大小。如果為True,則輸出大小會向上取整。默認為False。
-
count_include_pad:是否將填充值計算在內(nèi)。如果為True,則會將填充值計算在內(nèi)。默認為True。
-
divisor_override:用于覆蓋默認的輸出元素數(shù)。如果指定了該參數(shù),則輸出元素數(shù)將被覆蓋為該值。默認為None。
2.2.3 使用示例
- 張量池化
import torch# 定義輸入數(shù)據(jù)張量,大小為 (batch_size, channels, height, width)
input_tensor = torch.randn(2, 3, 16, 16)# 定義平均池化層,kernel_size 為池化核大小,stride 為步幅
avg_pool = torch.nn.AvgPool2d(kernel_size=2, stride=2)# 對輸入數(shù)據(jù)進行平均池化操作
output_tensor = avg_pool(input_tensor)# 輸出池化前后的結果張量大小
print("input_tensor:", input_tensor.shape)
print("output_tensor:", output_tensor.shape)
運行結果顯示:
input_tensor: torch.Size([2, 3, 16, 16])
output_tensor: torch.Size([2, 3, 8, 8])
- 圖片池化?
import torch
from PIL import Image
from torchvision.transforms import ToTensor
from torchvision.transforms.functional import to_pil_image
import matplotlib.pyplot as plt# 讀入示例圖片并將其轉(zhuǎn)換為 PyTorch 張量
img = Image.open('./data/lena.jpeg')
img_tensor = ToTensor()(img)# 定義 AvgPool2d 函數(shù),進行池化操作
avg_pool = torch.nn.AvgPool2d(kernel_size=2, stride=2)
img_pool = avg_pool(img_tensor.unsqueeze(0)).squeeze(0)# 將池化后的張量轉(zhuǎn)換為 PIL 圖像并保存
img_pool_pil = to_pil_image(img_pool)plt.subplot(121)
plt.imshow(img)
plt.title('original')
plt.axis('off')
plt.subplot(122)
plt.imshow(img_pool_pil)
plt.title('pool')
plt.axis('off')
plt.show()
?
2.2.4 總結
平均池化取每個矩形區(qū)域中的平均值,可以提取特征圖中所有特征的信息進入下一層,而不像最大池化只保留值最大的特征,所以平均池化可以更多保留些圖像的背景信息。
2.3 Global Average Pooling(全局平均池化)
在卷積神經(jīng)網(wǎng)絡訓練初期,卷積層通過池化層后一般要接多個全連接層進行降維,最后再Softmax分類,這種做法使得全連接層參數(shù)很多,降低了網(wǎng)絡訓練速度,且容易出現(xiàn)過擬合的情況。在這種背景下,M Lin等人提出使用全局平均池化Global Average Pooling[1]來取代最后的全連接層。用很小的計算代價實現(xiàn)了降維,更重要的是GAP極大減少了網(wǎng)絡參數(shù)(CNN網(wǎng)絡中全連接層占據(jù)了很大的參數(shù))。
論文地址: https://arxiv.org/pdf/1312.4400.pdf
代碼鏈接: https://worksheets.codalab.org/worksheets
2.3.1 定義
全局平均池化是一種特殊的平均池化,只不過它不劃分若干矩形區(qū)域,而是將整個特征圖中所有的元素取平均輸出到下一層。其定義如下:
2.3.2 總結
作為全連接層的替代操作,GAP對整個網(wǎng)絡在結構上做正則化防止過擬合,直接剔除了全連接層中黑箱的特征,直接賦予了每個channel實際的類別意義。除此之外,使用GAP代替全連接層,可以實現(xiàn)任意圖像大小的輸入,而GAP對整個特征圖求平均值,也可以用來提取全局上下文信息,全局信息作為指導進一步增強網(wǎng)絡性能。
2.4 Mix Pooling(混合池化)
論文地址:?http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.678.7068
2.4.1 定義
為了提高訓練較大CNN模型的正則化性能,受Dropout(將一半激活函數(shù)隨機設置為0)的啟發(fā),Dingjun Yu等人提出了一種隨機池化Mix Pooling[2] 的方法,隨機池化用隨機過程代替了常規(guī)的確定性池化操作,在模型訓練期間隨機采用了最大池化和平均池化方法,并在一定程度上有助于防止網(wǎng)絡過擬合現(xiàn)象。其定義如下:
2.4.2 總結
混合池化優(yōu)于傳統(tǒng)的最大池化和平均池化方法,并可以解決過擬合問題來提高分類精度。此外該方法所需要的計算開銷可忽略不計,而無需任何超參數(shù)進行調(diào)整,可被廣泛運用于CNN。
2.5 Stochastic Pooling(隨機池化)
論文地址:?https://arxiv.org/pdf/1301.3557
代碼鏈接:?https://github.com/szagoruyko/imagine-nn
2.5.1 定義
隨機池化Stochastic Pooling[3] 是Zeiler等人于ICLR2013提出的一種池化操作。隨機池化的計算過程如下:
??? 先將方格中的元素同時除以它們的和sum,得到概率矩陣。
??? 按照概率隨機選中方格。
??? pooling得到的值就是方格位置的值。
假設特征圖中Pooling區(qū)域元素值如下(參考Stochastic Pooling簡單理解):
則這時候的poolng值為1.5。使用stochastic pooling時(即test過程),其推理過程也很簡單,對矩陣區(qū)域求加權平均即可。比如對上面的例子求值過程為為:
說明此時對小矩形pooling后的結果為1.625。在反向傳播求導時,只需保留前向傳播已經(jīng)記錄被選中節(jié)點的位置的值,其它值都為0,這和max-pooling的反向傳播非常類似。本小節(jié)參考Stochastic Pooling簡單理解[4]。
2.5.2 總結
隨機池化只需對特征圖中的元素按照其概率值大小隨機選擇,即元素值大的被選中的概率也大,而不像max-pooling那樣,永遠只取那個最大值元素,這使得隨機池化具有更強的泛化能力。
2.6 Power Average Pooling(冪平均池化)
論文地址:?http://proceedings.mlr.press/v32/estrach14.pdf
2.7 Detail-Preserving Pooling(DPP池化)
論文地址: Saeedan_Detail-Preserving_Pooling_in_CVPR_2018_paper.pdf
代碼鏈接: https://github.com/visinf/dpp
為了降低隱藏層的規(guī)?;驍?shù)量,大多數(shù)CNN都會采用池化方式來減少參數(shù)數(shù)量,來改善某些失真的不變性并增加感受野的大小。由于池化本質(zhì)上是一個有損的過程,所以每個這樣的層都必須保留對網(wǎng)絡可判別性最重要的部分進行激活。但普通的池化操作只是在特征圖區(qū)域內(nèi)進行簡單的平均或最大池化來進行下采樣過程,這對網(wǎng)絡的精度有比較大的影響?;谝陨蠋c,Faraz Saeedan等人提出一種自適應的池化方法-DPP池化Detail-Preserving Pooling[6],該池化可以放大空間變化并保留重要的圖像結構細節(jié),且其內(nèi)部的參數(shù)可通過反向傳播加以學習。DPP池化主要受**Detail-Preserving Image Downscaling[7]**的啟發(fā)。
DPP池化允許縮減規(guī)模以專注于重要的結構細節(jié),可學習的參數(shù)控制著細節(jié)的保存量,此外,由于細節(jié)保存和規(guī)范化相互補充,DPP可以與隨機合并方法結合使用,以進一步提高準確率。
2.8 Local Importance Pooling(局部重要性池化)
論文地址: Gao_LIP_Local_Importance-Based_Pooling_ICCV_2019_paper.pdf
代碼鏈接: https://github.com/sebgao/LIP
CNN通常使用空間下采樣層來縮小特征圖,以實現(xiàn)更大的接受場和更少的內(nèi)存消耗,但對于某些任務而言,這些層可能由于不合適的池化策略而丟失一些重要細節(jié),最終損失模型精度。為此,作者從局部重要性的角度提出了局部重要性池化Local Importance Pooling[8],通過基于輸入學習自適應重要性權重,LIP可以在下采樣過程中自動增加特征判別功能。
Local Importance Pooling可以學習自適應和可判別性的特征圖以匯總下采樣特征,同時丟棄無信息特征。這種池化機制能極大保留物體大部分細節(jié),對于一些細節(jié)信息異常豐富的任務至關重要。
2.9 Soft Pooling(軟池化)
論文地址:?https://arxiv.org/pdf/2101.00440
代碼鏈接:?https://github.com/alexandrosstergiou/SoftPool
現(xiàn)有的一些池化方法大都基于最大池化和平均池化的不同組合,而軟池化Soft Pooling[9] 是基于softmax加權的方法來保留輸入的基本屬性,同時放大更大強度的特征激活。與maxpooling不同,softpool是可微的,所以網(wǎng)絡在反向傳播過程中為每個輸入獲得一個梯度,這有利于提高訓練效果。
SoftPool的計算流程如下:
- a. 特征圖透過滑動視窗來框選局部數(shù)值
- b. 框選的局部數(shù)值會先經(jīng)過指數(shù)計算,計算出的值為對應的特征數(shù)值的權重
- c. 將各自的特征數(shù)值與其相對應的權重相乘
- d. 最后進行加總
這樣的方式讓整體的局部數(shù)值都有所貢獻,重要的特征占有較高的權重。比Max pooling(直接選擇最大值)、Average pooling (求平均,降低整個局部的特征強度) 能夠保留更多訊息。
??? SoftPool的數(shù)學定義如下:
計算特征數(shù)值的權重,其中R為框選的局部區(qū)域,a為特征數(shù)值
作為一種新穎地池化方法,SoftPool可以在保持池化層功能的同時盡可能減少池化過程中帶來的信息損失,更好地保留信息特征并因此改善CNN中的分類性能。大量的實驗結果表明該算法的性能優(yōu)于原始的Avg池化與Max池化。隨著神經(jīng)網(wǎng)絡的設計變得越來越困難,而通過NAS等方法也幾乎不能大幅度提升算法的性能,為了打破這個瓶頸,從基礎的網(wǎng)絡層優(yōu)化入手,不失為一種可靠有效的精度提升手段。
?