1. 卷积算子-convolution
--卷积操作的本质是将一个滤波器或卷积核应用于输入数据的局部区域,并将输出与其他区域进行叠加,以获得一张特征图。
下面说明pytorch中卷积的主要参数:
torch.nn.Conv2d( in_channels, out_channels, kernel_size, stride, padding,
dilation, groups, bias, padding_mode, device, dtype )
in_channels : 输入图像的通道数
out_channels : 输出图像的通道数
kernel_size : 卷积核心的大小:int=[a,b]或a
stride : 卷积核每次操作完移动的步幅
padding : 在输入的图像边缘做填充操作,控制padding_mode的数量
padding_mode : padding填充模式,默认为zero_padding
dilation : 设置空洞卷积/扩张卷积
groups : 控制分组卷积参数。即对图像的输入通道分组,减少训练的参数,
可以分别在不同的GPU上训练,加快训练速度
bias : 在输出中添加一个可学习的偏差,默认设置为True
device : 卷积操作可以在GPU或CPU上运行
dtype : 类型
几个关键问题:
(1). 输入通道、输出通道、卷积核心的关系?
构造的卷积核心为[C2, C1, K1, K2]
其中, C2 为构造的卷积核的数量, 同时也是图像/特征图输出的通道数量---->out_channels。
C1 是上层卷积层网络产生的通道数,或者输入图像/特征图的通道数---->in_channels。
K1,K2是构造的卷积核的高和宽,有些参考资料说是卷积窗口的大小。
图像的输入通道 : C1个卷积核分别与每个输入图像通道上的特征图做二维互相关运算,算出的结 果再按照图像/特征图的对应位置相加---> 多输入通道经过卷积核运算最终只会产生一张特征图
图像的输出通道: 设置多个的卷积核,最终产生多个输出通道
(2). 多输入多输出通道在神经网络中,如何展现神经元数量
图像经过多少次卷积层运算,每层卷积运算都会产生对应的特征图的数量 ,每个网络层的特 征图就是神经网络中的神经元。
(3). 图像经过卷积层以后,图像的形状变化关系?
其中 nout : 图像/特征图经过一次卷积操作以后的大小
nin : 特征图的尺寸大小
f : 卷积核心的大小
p : 设置填补的参数,2p是在原特征图的两边做填补
s : 卷积核移动的步幅
(4).空洞卷积?
空洞卷积就是在卷积核中相邻元素之间插入0,变成新的卷积核。在torch.nn.conv2d()中的参数设置为dilation,默认的dilation=1。通过设置dilation参数用来调整卷积核的大小,调整后的卷积核的尺寸和原来卷积核的尺寸大小的关系为:
其中: f : 设置卷积核的大小,即kernel_size的大小
d : dilation设置的大小
f' : 空洞卷积的卷积核心的大小
---> (f-1) 的本质就是卷积核中元素与元素的间隔数量,(d-1)本质在卷积核中元素间隔内插入0的个数,也被称为dilation_rate
import torch
import torch.nn as nn
x= torch.randn(1000,3,28,28)
conv_layer = nn.Conv2d(in_channels=3,out_channels=32,kernel_size=(3,3),stride=1,padding=1,dilation=(2,2))
out = conv_layer(x)
print(out.shape)
(5). 分组卷积
对输入图像/特征图进行分组卷积,用来加快训练速度。注意分的组数一定要被输入通道数整除,不然会报错。
2. 池化算子-pooling
--用来减小特征图的大小,从而减小网络中的参数量核计算量。池化层没有训练参数
a: 以下为最大池化,其本质就是找出小范围内的最大值。设置小范围的大小的参数为kernel_size。
torch.nn.Maxpool2d(kernel_size , stride , padding , dilation , return_indices , ceil_mode)
kernel_size : 做池化的窗口,可以是int也可以是tuple
stride : 池化窗口的移动步长
padding : 图像每条边填补0的层数
dilation : 卷积对输入数据的空间间隔
return_indices : 如果等于True,返回输出最大值的序号,对上采样操作会有帮助
ceil_mode : 如果等于True,计算输出信号大小的时候,会使用向上取整,代替默认向下取整
b: 以下为平均池化,其本质就是将确定的小范围内的数据求解平均值。
class AvgPool2d( kernel_size, stride, padding, ceil_mode, count_include_pad,
divisor_override
)
c:由于特征图的输出通道数是已知的,在使用自适应最大池化或者自适应平均池化的时候,只需要确定输出特征图的大小即可,如下
torch.nn.AdaptiveAvgPool2d(output_size)
torch.nn.AdaptiveMaxPool2d(output_size,return_indices)
import torch
import torch.nn as nn
m = nn.AdaptiveMaxPool2d((5,7))
input = torch.randn(1, 64, 8, 9)
#output = m(input) #------>输出形状为[1,64,5,7]
# t输出大小为正方形 7x7
m = nn.AdaptiveMaxPool2d(7)
input = torch.randn(1, 64, 10, 9)
#output = m(input) #------>输出形状为[1,64,7,7]
m = nn.AdaptiveMaxPool2d((None, 7))
input = torch.randn(1, 64, 10, 9)
#output = m(input) #----->输出形状为[1,64,10,7]
m = nn.AdaptiveMaxPool2d((1))
input = torch.randn(1, 64, 10, 9)
output = m(input) #------>输出形状为[1,64,1,1]
print(output.shape)
随着很多学者对于卷积的研究的深入,往后设计的深度学习的网络模型逐渐少见池化层操作,直接采用卷积操作设置padding和stride来设定图像的降采样。
3. 全连接层
传统机器学习中多层感知机(MLP,Multi_layer Perceptron)就是深度学习中的全连接层。
全连接层的本质是矩阵的乘积运算,而矩阵可以看作是一种改变数据形状的特殊函数。
torch.nn.Linear(in_features, out_features, bias, device, dtype)
in_channel : 输入特征的维度
out_channel : 输出特征的维度
bias : 是否添加偏置
device : 设备
dtype : 类型
4. Normalization操作
是数据处理中的一种非常重要的方法,通常将不同尺度或单位的数据特征缩放到相同的范围内。使得数据的均值为0,方差为1,从而使得数据分布更加稳定和可控。可以提高模型的精度和效率以及简化模型的复杂性。
计算方法如下图:
torch.nn.BatchNorm2d(
num_features: int,
eps: float = 0.00001,
momentum: float = 0.1,
affine: bool = True,
track_running_stats: bool = True,
device: Any | None = None,
dtype: Any | None = None
)
使用方法:
a 在卷积层中使用:一定要在卷积 操作之后,激活函数之前。
import troch
from torch import nn
nn.Conv2d(3, 32, 3, 1, 1)
nn.BatchNorm2d(32) # 注意在卷积后,激活函数前。【维度是卷积层的输出维度哦】
nn.ReLU()
b 在全连接层中使用,也是全连接后,激活函数前
import torch
from torch import nn
nn.Linear(512,128)
nn.BatchNorm2d(128) #在linear后面,在sigmoid前面。【维度是linear的输出维度哦】
nn.Sigmoid()
5. Dropout层
在全连接网络中,不同层的每个神经元都要被相邻层的神经元学习。如下左图,这样容易导致模型过拟合。Dropout是一类通用的正则化方法 ,
Dropout在训练过程中随机的丢弃一部分输入 , 此时丢弃部分对应的参数不会更新
相当于Dropout是一个集成方法, 将所有子网络结果进行合并,通过随机丢弃 , 输入可以得到各种子网络。
6. 转置卷积
在前面的内容中,卷积和池化过程都是实现图像的下采样的过程。这里简单介绍转置卷积以及其他上采样的方法。
torch.nn.ConvTranspose2d(in_channels,out_channels,kernel_size,stride,padding,
output_padding,bias,dilation)
in_channels : 输入通道数
out_channels : 输出通道数
kernel_size : 卷积核的大小
stride : 放大倍数
padding : 输出图像高宽减少的行数或列数
output_padding : 对输出图像行和列增加的数量,用以补偿图像的尺寸问题
groups : int = 1,
bias : bool = True,
dilation : int = 1,
padding_mode : str = 'zeros',
转置卷积的输入和输出图像的尺寸的关系:
通过上面式子可以看出,stride是对图像放大起着至关重要的因素。
import torch
import torch.nn as nn
x = torch.randn(1,1,128,128)
ConT = nn.ConvTranspose2d(in_channels=1, out_channels=2, kernel_size=3, stride=2)
y = ConT(x)
print(y.shape)
--> torch.Size([1, 2, 257, 257])
#########################################################################
x = torch.randn(1,1,128,128)
ConT = nn.ConvTranspose2d(in_channels=1, out_channels=2, kernel_size=3,
padding=1, stride=2)
y = ConT(x)
print(y.shape)
--> torch.Size([1, 2, 255, 255])
#########################################################################
x = torch.randn(1,1,128,128)
ConT = nn.ConvTranspose2d(in_channels=1, out_channels=2, kernel_size=3,
padding=1, stride=2, output_padding=1)
y = ConT(x)
print(y.shape)
--> torch.Size([1, 2, 256, 256])
########################################################################
x = torch.randn(1,1,128,128)
ConT = nn.ConvTranspose2d(in_channels=1, out_channels=2, kernel_size=3,
padding=1, stride=4, output_padding=1)
y = ConT(x)
print(y.shape)
--> torch.Size([1, 2, 510, 510])
然而,除了转置卷积可以实现上采样,还有其他的一些方法:
其中scale_factor是放大倍数;
mode的可选参数分别为:nearest,
linear,
bilinear,
bicubic,
trilinear'
. 默认使用
'nearest'
troch.nn.Upsample(
size: _size_any_t | None = None,
scale_factor: _ratio_any_t | None = None,
mode: str = 'nearest',
align_corners: bool | None = None,
recompute_scale_factor: bool | None = None
)
torch.nn.UpsamplingNearest2d(size=None, scale_factor=None)
torch.nn.UpsamplingBilinear2d(size=None, scale_factor=None)