官網連結:
nn.MaxPool2d是在進行影象處理時,Pool layers最常用的函數
class torch.nn.MaxPool2d(kernel_size, stride=None, padding=0, dilation=1, return_indices=False, ceil_mode=False)
kernel_size(int or tuple): 用於設定一個取最大值的視窗,如設定為3,那麼會生成一個3×3的視窗
stride(int or tuple): 預設值為kernel_size,步幅,和折積層中的stride一樣
padding(int or tuple): 填充影象,預設填充的值為0
dilation(int): 空洞折積,即折積核之間的距離。如折積核的尺寸為3×3,dilation為1,那麼返回一個大小為5×5的折積核,折積核每個元素與上下左右的元素之間空一格
return_indices(bool): 一般用的很少,不做介紹
ceil_mode(bool): 預設為False。為True時,輸出的shape使用ceil格式(向上取整,即進一);為False時,輸出的shape使用floor格式(向下取整)。
假設有一個5×5的影象和一個3×3的池化核(kenel_size=3),如下圖。池化過程就是將池化核與影象進行匹配。下面介紹最大池化的具體操作。
首先用池化核覆蓋影象,如下圖。然後取到最大值,作為一個輸出。
上圖為第一次最大池化操作,最大值為2。將2作為一個輸出,如下圖。
由於本例未對stride進行設定,故stride採取預設值,即stride=kernel_size=3,池化核移動如下圖(移動方式與上上文中提到的折積核移動方式相同,不再贅述)。由於池化核移動已超出範圍,要不要取這3×2部分的最大值,取決於call_mode的值,若ceil_mode=True,則取最大值,即輸出3;若ceil_mode=False,則不取這部分的值,即這一步不進行池化操作。
假設ceil_mode=True,經過最大池化操作後,輸出的結果如下圖。
假設ceil_mode=False,經過最大池化操作後,輸出的結果如下圖。
跟折積操作的計算公式一樣。具體如下:
引數說明:
N: 影象的batch_size
C: 影象的通道數
H: 影象的高
W: 影象的寬
計算過程:
Input:\( (N,C_{in},H_{in},W_{in})\) or \((C_{in},H_{in},W_{in})\)
Output: \((N,C_{out},H_{out},W_{out})\) or \((C_{out},H_{out},W_{out})\)
其中有:
\(H_{out}=⌊\frac{H_{in}+2×padding[0]−dilation[0]×(kernel\_size[0]−1)−1}{stride[0]}+1⌋\)
\(W_{out}=⌊\frac{W_{in}+2×padding[1]−dilation[1]×(kernel\_size[1]−1)−1}{stride[1]}+1⌋\)
看論文的時候,有些比如像padding這樣的引數不知道,就可以用這條公式去進行推導
依然選取上面的例子,進行程式設計。
import torch
from torch import nn
from torch.nn import MaxPool2d
input=torch.tensor([[1,2,0,3,1],
[0,1,2,3,1],
[1,2,1,0,0],
[5,2,3,1,1],
[2,1,0,1,1]],dtype=torch.float32) #輸入影象資料;與折積操作不同的是,最大池化操作要求輸入的影象資料是浮點數,而不是整數(為整數第23行會報錯)
input=torch.reshape(input,(-1,1,5,5)) #構造影象資料,使其符合輸入標準,即分別為(輸入batch_size待定,1通道,大小為5×5)
print(input.shape) #[Run] torch.Size([1, 1, 5, 5]);資料格式符合輸入標準
#構造神經網路
class Demo(nn.Module):
def __init__(self):
super(Demo,self).__init__()
self.maxpool1=MaxPool2d(kernel_size=3,ceil_mode=True) #設定最大池化函數,這裡以ceil_mode=True為例
def forward(self,input):
output=self.maxpool1(input) #將輸入的資料(input)進行最大池化草子哦
return output
demo=Demo() #建立神經網路
output=demo(input)
print(output)
"""
[Run]
tensor([[[[2., 3.],
[5., 1.]]]])
符合前面ceil_mode=True例子的輸出結果一致
"""
最大程度地保留輸入特徵,並使資料量減小
上述例子中輸入影象為5×5,經過最大池化操作之後變成了3×3,甚至為1×1。使得影象特徵得以保留,而資料量大大減少了,對整個網路來說引數減少了,運算速度也變快了
打個比方,這就像看視訊的時候,高清(輸入影象)變(經過最大池化操作)標清(輸出資料)
使用具體圖片範例,介紹最大池化的作用:
from torch import nn
from torch.nn import MaxPool2d
import torchvision
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter
dataset=torchvision.datasets.CIFAR10("./dataset",train=False,download=True,transform=torchvision.transforms.ToTensor())
dataloder=DataLoader(dataset,batch_size=64)
#構造神經網路
class Demo(nn.Module):
def __init__(self):
super(Demo,self).__init__()
self.maxpool1=MaxPool2d(kernel_size=3,ceil_mode=True) #設定最大池化函數,這裡以ceil_mode=True為例
def forward(self,input):
output=self.maxpool1(input) #將輸入的資料(input)進行最大池化草子哦
return output
demo=Demo() #建立神經網路
writer=SummaryWriter("logs_maxpool")
step=0
for data in dataloder:
imgs,targets=data
writer.add_images("input",imgs,step)
output=demo(imgs)
writer.add_images("output",output,step)
step+=1
writer.close()
對比輸入輸出,可以看出影象更糊了