目录
1.池化层
1.1 概述
池化层 (Pooling) 降低维度, 缩减模型大小,提高计算速度. 即: 主要对卷积层学习到的特征图进行下采样(SubSampling)处理。
池化层主要有两种:
-
最大池化 max pooling
最大池化是从每个局部区域中选择最大值作为池化后的值,这样可以保留局部区域中最显著的特征。最大池化在提取图像中的纹理、形状等方面具有很好的效果。
-
平均池化 avgPooling
平均池化是将局部区域中的值取平均作为池化后的值,这样可以得到整体特征的平均值。平均池化在提取图像中的整体特征、减少噪声等方面具有较好的效果。
1.2 池化层计算

1.3 步长Stride

1.4 边缘填充Padding

1.5 多通道池化计算
在处理多通道输入数据时,池化层对每个输入通道分别池化,而不是像卷积层那样将各个通道的输入相加。这意味着池化层的输出和输入的通道数是相等。
1.6 池化层的作用
池化的优势:
-
通过降低特征图的尺寸,池化层能够减少计算量,从而提升模型的运行效率。
-
池化操作可以带来特征的平移、旋转等不变性,这有助于提高模型对输入数据的鲁棒性。
-
池化层通常是非线性操作,例如最大值池化,这样可以增强网络的表达能力,进一步提升模型的性能。
池化的缺点:
-
池化操作会丢失一些信息。
最大池化:
import torch.nn as nn
import torch
torch.random.manual_seed(0)
# 输入的特征图数据
input = torch.randint(0,225,(1,64,224,224),dtype=torch.float32)
pool = nn.MaxPool2d(
kernel_size =2,# 池化核大小
stride = 2,# 步长
return_indices = True,# 返回索引
)
output,indices = pool(input)
print(input[0] [0] [:10, :10])
print(output[0] [0] [:10, :10])
print(indices[0] [0] [:5, :5])
平均池化:
import torch.nn as nn
import torch
torch.random.manual_seed(0)
# 输入的特征图数据
input = torch.randint(0,225,(1,64,224,224),)
pool = nn.AvgPool2d(
kernel_size =2,# 池化核大小
stride = 2,# 步长
ceil_mode =False,
)
output= pool(input)
print(input[0] [0] [:10, :10])
print(output[0] [0] [:5, :5])
2. 卷积拓展
2.1 二维卷积
分单通道版本和多通道版本。
2.1.1 单通道版本
只有一个通道的卷积叫做二维卷积(单通道卷积版本)。
2.1.2 多通道版本
彩色图像拥有R、G、B这三层通道,因此我们在卷积时需要分别针对这三层进行卷积。最后将三个通道的卷积结果进行合并(元素相加),得到卷积结果。
2.2 三维卷积
二维卷积是在单通道的一帧图像上进行滑窗操作,输入是高度H宽度W的二维矩阵。
而如果涉及到视频上的连续帧或者立体图像中的不同切片,就需要引入深度通道,此时输入就变为高度H宽度W*深度C的三维矩阵。
不同于二维卷积核只在两个方向上运动,三维卷积的卷积核会在三个方向上运动,使得三维卷积能够有效地描述3D空间中的对象关系,它在一些应用中具有显著的优势,例如3D对象的分割以及医学图像的重构等。
2.3 反卷积
卷积是对输入图像及进行特征提取,这样会导致尺寸会越变越小,而反卷积是进行相反操作。并不会完全还原到跟输入图一样,只是保证了与输入图像尺寸一致,主要用于向上采样。从数学上看,反卷积相当于是将卷积核转换为稀疏矩阵后进行转置计算。也被称为转置卷积。
反卷积计算过程
如图,在2x2的输入图像上使用【步长1、边界全0填充】的3x3卷积核,进行转置卷积(反卷积)计算,向上采样后输出的图像大小为4x4。

2.4 空洞卷积(膨胀卷积)
为扩大感受野,在卷积核的元素之间插入空格“膨胀”内核,形成“空洞卷积”(或称膨胀卷积),并用膨胀率参数L表示要扩大内核的范围,即在内核元素之间插入L-1个空格。当L=1时,则内核元素之间没有插入空格,变为标准卷积。图中是L=2的空洞卷积。

import torch
import torch.nn as nn
import numpy as np
class Network(nn.Module):
def __init__(self):
super(Network,self).__init__()
self.conv = nn.Conv2d(
in_channels= 1,
out_channels =1,
kernel_size = (3,3),
stride = 1,
padding=0,
dilation=3# 膨胀
)
def forward(self,x):
x = self.conv(x)
return x
torch.random.manual_seed(0)
input = torch.randint(0,255,(1,1,32,32),dtype=torch.float32)
model = Network()
output = model(input)
print(output.shape)
2.5 可分离卷积
2.5.1 空间可分离卷积
空间可分离卷积是将卷积核分解为两项独立的核分别进行操作。
import torch
import torch.nn as nn
import numpy as np
class Network(nn.Module):
def __init__(self):
super(Network,self).__init__()
self.conv = nn.Conv2d(
in_channels= 1,
out_channels =1,
kernel_size = (3,3),
bias = False,
)
def forward(self,x):
x = self.conv(x)
return x
class Network2(nn.Module):
def __init__(self):
super(Network2,self).__init__()
self.conv = nn.Conv2d(
in_channels= 1,
out_channels =1,
kernel_size = (1,3),# 空间可分离卷积
bias = False,
)
self.conv2 = nn.Conv2d(
in_channels= 1,
out_channels =1,
kernel_size = (3,1),# 空间可分离卷积
bias = False,
)
def forward(self,x):
x = self.conv(x)
x = self.conv2(x)
return x
torch.random.manual_seed(0)
input=torch.randint(0,255,(1,1,32,32),dtype=torch.float32)
model1= Network()
model2= Network2()
# for name,param in model1.named_parameters():# 参数量:8*8*3*3 =576
# print(name,param.shape)
# for name,param in model2.named_parameters():# 参数量:8*1*3*3+8*8 = 136
# print(name,param.shape)
model1.conv.weight.data=torch.tensor([[[[0.1500, 0.2000, 0.2500],[0.2100, 0.2800, 0.3500],[0.2400, 0.3200, 0.4000]]]])
# for name,param in model1.named_parameters():
# print(name,param)
model2.conv.weight.data=torch.tensor([[[[0.3,0.4,0.5]]]])
model2.conv2.weight.data=torch.tensor([[[[0.5],[0.7],[0.8]]]])
# for name,param in model2.named_parameters():
# print(name,param)
output1 = model1(input)
output2 = model2(input)
# 查看结果是否一样
print(output1[:,:,:5,:5])
print(output2[:,:,:5,:5])
2.5.2 深度可分离卷积
深度可分离卷积由两部组成:深度卷积和1x1卷积。
输入图的每一个通道,都使用了对应的卷积核进行卷积。 输入通道数量 = 卷积核个数。
对输出内容进行数量为通道个数的1x1的卷积。输出通道数量 = 卷积核个数。
import torch
import torch.nn as nn
import numpy as np
class Network(nn.Module):
def __init__(self):
super(Network,self).__init__()
self.conv = nn.Conv2d(
in_channels= 8,
out_channels =8,
kernel_size = (3,3),
bias = False,
)
def forward(self,x):
x = self.conv(x)
return x
class Network2(nn.Module):
def __init__(self):
super(Network2,self).__init__()
self.conv = nn.Conv2d(
in_channels= 8,
out_channels =8,
kernel_size = (3,3),
groups = 8, # 空间可分离卷积
bias = False
)
self.conv2 = nn.Conv2d(
in_channels= 8,
out_channels =8,
kernel_size = (1,1),# 空间可分离卷积
bias = False
)
def forward(self,x):
x = self.conv(x)
x = self.conv2(x)
return x
# 输入的特征图数据
input = torch.randint(0,225,(1,8,32,32),dtype=torch.float32)
model1= Network()
model2= Network2()
output1 = model1(input)
output2 = model2(input)
for name,param in model1.named_parameters():# 参数量:8*8*3*3 =576
print(name,param.shape)
for name,param in model2.named_parameters():# 参数量:8*1*3*3+8*8 = 136
print(name,param.shape)
2.6 扁平卷积
扁平卷积是将标准卷积拆分成为3个1x1的卷积核,然后再分别对输入层进行卷积计算。

-
标准卷积参数量X*Y*C,计算量为M*N*C*X*Y
-
拆分卷积参数量(X+Y+C),计算量为M*N*(C+X+Y)
2.7 分组卷积
2012年,AlexNet论文中最先提出来的概念,当时主要为了解决GPU显存不足问题,将卷积分组放到两个GPU中并行执行。
2.8 混洗分组卷积
分组卷积中最终结果会按照原先的顺序进行合并组合,阻碍了模型在训练时特征信息在通道间流动,削弱了特征表示。混洗分组卷积,主要是将分组卷积后的计算结果混合交叉在一起输出。
在分组卷积中,卷积核被分成不同的组,每组负责对相应的输入层进行卷积计算,最后再进行合并。

3.感受野
3.1 理解感受野
字面意思是感受的视野范围,为得到一个特征值,输入数据的size。
3.2 感受野的作用
卷积核所需的参数更少一些。
卷积过程越多,特征提取也会越细致,加入的非线性变换也随着增多 。
4253

被折叠的 条评论
为什么被折叠?



