【pytorch】卷积操作原理解析与nn.Conv2d用法详解

参考:

https://pytorch.org/docs/master/generated/torch.nn.Conv2d.html#torch.nn.Conv2d

https://zhuanlan.zhihu.com/p/251068800

https://www.cnblogs.com/mrlonely2018/p/13946730.html

https://www.jb51.net/article/177739.htm

https://www.jianshu.com/p/a6da4ad8e8e7

https://blog.csdn.net/HappinessSourceL/article/details/106207022

1 官方文档

在这里插入图片描述在这里插入图片描述

在这里插入图片描述

2 函数原型及参数介绍

函数原型:

class torch.nn.Conv2d(in_channels, 
					  out_channels,
				       kernel_size,
						stride=1, 
						padding=0, 
						dilation=1, 
						groups=1, 
						bias=True)

函数作用:定义一个卷积核,方便后面进行二维卷积操作
我们会发现一个现象:pytorch的conv2d没有要求输入卷积核的信息,设置卷积核的权重可以在后面采用:

conv_zeros = torch.nn.Conv2d(1,1,1,1,padding=1,padding_mode='zeros',bias=False)
conv_zeros.weight = torch.nn.Parameter(torch.ones(1,1,1,1))

Parameters:

参数数据类型
in_channelsintNumber of channels in the input image输入图像通道数
out_channelsintNumber of channels produced by the convolution卷积产生的通道数
kernel_size(int or tuple)Size of the convolving kernel卷积核尺寸,可以设为1个int型数或者一个(int, int)型的元组。例如(2,3)是高2宽3卷积核
stride(int or tuple, optional)Stride of the convolution. Default: 1卷积步长,默认为1。可以设为1个int型数或者一个(int, int)型的元组。
padding(int or tuple, optional)Zero-padding added to both sides of the input. Default: 0填充操作,控制padding_mode的数目。简言之,就是决定图像边沿填充的方式
padding_mode(string, optional)optional) ‘zeros’, ‘reflect’, ‘replicate’ or ‘circular’. Default: ‘zeros’padding模式,默认为Zero-padding 。
dilation(int or tuple, optional)Spacing between kernel elements. Default: 1扩张操作:控制kernel点(卷积核点)的间距,默认值:1。
groups(int, optional)Number of blocked connections from input channels to output channels. Default: 1group参数的作用是控制分组卷积,默认不分组,为1组。输入图像通道数
bias(bool, optional)If True, adds a learnable bias to the output. Default: True为真,则在输出中添加一个可学习的偏差。默认:True。

3 关于二维卷积:

首先我们介绍以下基本的卷积运算:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
可以看出,上图的卷积运算实质上就是两个相同尺寸的矩阵进行了一次矩阵内积运算。

实际上,一次卷积操作要经过很多次上述的矩阵内积运算,最终也会获得一个新的矩阵。

(1)单通道卷积

下图可以看作是一次常规的卷积操作:
这是用一个卷积核在一个二维图像上进行卷积操作后得到一个二维的特征映射。
在这里插入图片描述

可以看出卷积核尺寸为3*3kernel_size=3,卷积步长为1stride=1
输入通道in_channels和输出通道out_channels不得而知,假设都为1。
关于padding后面介绍,暂定为padding=0

代码:

 nn.Conv2d(in_channels=1,out_channels=1,kernel_size=3,stride=1,padding=0)

(2)多通道卷积

若是出现in_channels>1,out_channels=1,则可以参考下图的卷积运算:

在这里插入图片描述卷积过程如下,每一个通道的像素值与对应的卷积核通道的数值进行卷积,因此每一个通道会对应一个输出卷积结果,三个卷积结果对应位置累加求和,得到最终的卷积结果(这里卷积输出结果通道只有1个,因为卷积核只有1个。卷积多输出通道下面会继续讲到)。
可以这么理解:最终得到的卷积结果是原始图像各个通道上的综合信息结果。

代码:

 nn.Conv2d(in_channels=3,out_channels=1,kernel_size=3,stride=1,padding=0)

上述过程中,每一个卷积核的通道数量,必须要求与输入通道数量一致,因为要对每一个通道的像素值要进行卷积运算,所以每一个卷积核的通道数量必须要与输入通道数量保持一致

在这里插入图片描述

(3)多通道输入,多通道输出

在这里插入图片描述
代码:

 nn.Conv2d(in_channels=3,out_channels=3,kernel_size=1,stride=1,padding=0)

4 卷积操作后图形尺寸的变化公式:

input_size: 输入图形的尺寸
output_size: 输出图形的尺寸
kernel_size: 卷积核的尺寸
stride: 步长
padding: 边缘扩充

output_size = ((input_size - dilation*(kernel_size-1) + 2* padding)-1)/stride + 1
注:整除

常见举例:

input_size=(512,512)

conv2d(in_channels,out_channels,kernel_size=3,stride=2, padding=1)
# 求output_size:
output_size = (input_size - kernel_size + 2* padding)/stride + 1
output = (512 - 3 +2)/2+1 = 255+1 = 256

input_size=(128,128)

conv2d(in_channels,out_channels,kernel_size=3,stride=1, padding=1)
# 求output_size:
output_size = (input_size - kernel_size + 2* padding)/stride + 1
output = (128 - 3 +2)/1+1 = 127+1 = 128

5 关于参数 padding与padding_mode:

(1)padding的理解:

padding参数作用:控制zero-padding的数目。
用容易理解的语言来说:padding就是在图像四周加格子。

原因:如果不对图像边缘进行填充,卷积核将无法到达图像边缘的像素,而且卷积前后图像的尺寸也会发生变化,这会造成许多麻烦。
因此现在各大深度学习框架的卷积层实现上基本都配备了padding操作,以保证图像输入输出前后的尺寸大小不变。

例如,若卷积核大小为3x3,那么就应该设定padding=1,即填充1层边缘像素;若卷积核大小为7x7,那么就应该设定padding=3,填充3层边缘像素;也就是padding大小一般设定为核大小的一半。在pytorch的卷积层定义中,默认的padding为零填充。

(2) PyTorch Conv2d中的padding_mode四种填充模式解析

padding,即边缘填充,可以分为四类:零填充,常数填充,镜像填充,重复填充。
padding_mode参数,可选项有4种:

(1) zeros,代表零填充。padding_mode默认选项为zeros

即在矩阵的高、宽两个维度上用0进行填充,填充时将在一个维度的两边都进行填充:

torch.nn.Conv2d(1,1,1,1,padding=1,padding_mode='zeros',bias=False)

(2) reflect,代表镜像填充。
reflect是以矩阵边缘为对称轴,将矩阵中的元素对称的填充到最外围。

torch.nn.Conv2d(1,1,1,1,padding=1,padding_mode='reflect',bias=False)

(3) replicate,代表重复填充。
对图像或者张量的边缘进行重复填充,就是说直接用边缘的像素值来填充。示例如下:

torch.nn.Conv2d(1,1,1,1,padding=1,padding_mode='replicate',bias=False)

(4) circular,代表循环填充。
示例如下:

# 定义一个1*1卷积,设置填充模式为'circular',在高和宽维度上两边各填充1个单位
In [64]: conv_reflect = torch.nn.Conv2d(1,1,1,1,padding=1,padding_mode='circular',bias=False)

# 将卷积核的权重设置为1,这样可使卷积后的输出即为填充后的输入矩阵
In [65]: conv_reflect.weight = torch.nn.Parameter(torch.ones(1,1,1,1))

# 进行卷积计算,并输出结果
In [66]: conv_circular(x)
Out[66]:
tensor([[[[16., 13., 14., 15., 16., 13.],
          [ 4.,  1.,  2.,  3.,  4.,  1.],
          [ 8.,  5.,  6.,  7.,  8.,  5.],
          [12.,  9., 10., 11., 12.,  9.],
          [16., 13., 14., 15., 16., 13.],
          [ 4.,  1.,  2.,  3.,  4.,  1.]]]], grad_fn=<ThnnConv2DBackward>)

6 关于参数dilation:

dilation:控制kernel点(卷积核点)的间距,默认值:1。

(1)dilation=0的话,效果如图:
在这里插入图片描述
蓝色(下面)为输入,绿色(上面)为输出,卷积核为3*3,此时为密集连接。

(2)dilation=1,那么效果如图:
称为扩张卷积(也叫空洞卷积)

在这里插入图片描述
优点:

这样单次计算时覆盖的面积(即感受域)由dilation=0时的3*3=9变为了dilation=1时的5*5=25
在增加了感受域的同时却没有增加计算量,保留了更多的细节信息,对图像还原的精度有明显的提升。

7 关于参数groups——分组卷积:

Group Convolution顾名思义,则是对输入feature map进行分组,然后每组分别卷积。

在这里插入图片描述
当group=1时,该卷积层需要6611=36个参数,即需要6个61*1的卷积核

计算时就是6H_inW_in的输入整个乘以一个611的卷积核,得到输出的一个channel的值,即1H_outW_out。这样经过6次与6个卷积核计算就能够得到6H_outW_out的结果了

如果将group=3时,卷积核大小为torch.Size([6, 2, 1, 1]),即6个211的卷积核,只需要需要621*1=12个参数

那么每组计算就只被in_channels/groups=2个channels的卷积核计算,当然这也会将输入分为三份大小为2H_inW_in的小输入,分别与211大小的卷积核进行三次运算,然后将得到的3个2H_outW_out的小输出concat起来得到最后的6H_outW_out输出

在实际实验中,同样的网络结构下,这种分组的卷积效果是好于未分组的卷积的效果的。

为什么要设置groups参数,有什么优点?

为了在GPU上并行计算:

标准卷积的计算如下图:

举个例子,假设有一个3×3大小的卷积层,其输入通道为16、输出通道为32。
那么一般的操作就是用32个3×3的卷积核来分别同输入数据卷积,这样每个卷积核需要3×3×16个参数,得到的输出是只有一个通道的数据。之所以会得到一通道的数据,是因为刚开始3×3×16的卷积核的每个通道会在输入数据的每个对应通道上做卷积,然后叠加每一个通道对应位置的值,使之变成了单通道,那么32个卷积核一共需要(3×3×16)×32 =4068个参数。
在这里插入图片描述

分组卷积的计算:

在这里插入图片描述
在这里插入图片描述

9 标准卷积的详细计算图可表示为:

在这里插入图片描述

10 案例代码:

>>> # With square kernels and equal stride
>>> m = nn.Conv2d(16, 33, 3, stride=2)
>>> # non-square kernels and unequal stride and with padding
>>> m = nn.Conv2d(16, 33, (3, 5), stride=(2, 1), padding=(4, 2))
>>> # non-square kernels and unequal stride and with padding and dilation
>>> m = nn.Conv2d(16, 33, (3, 5), stride=(2, 1), padding=(4, 2), dilation=(3, 1))
>>> input = torch.randn(20, 16, 50, 100)
>>> output = m(input)

  • 31
    点赞
  • 118
    收藏
    觉得还不错? 一键收藏
  • 11
    评论
nn.conv2dPyTorch中用于实现二维卷积操作的函数。它是torch.nn模块中的一部分,并且是构建卷积神经网络的常用操作之一。 函数签名如下: ```python torch.nn.Conv2d(in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True) ``` 参数解释: - in_channels:输入张量的通道数(例如,RGB图像的通道数为3) - out_channels:输出张量的通道数,即卷积核的数量,决定了卷积层的输出特征图的深度 - kernel_size:卷积核的大小,可以是一个整数(表示正方形卷积核)或一个元组(表示矩形卷积核) - stride:卷积操作的步长,默认为1 - padding:输入张量周围要填充的像素数,默认为0。padding可以用来保持输入输出尺寸相同,以允许更多的感受野。 - dilation:卷积核元素之间的间隔,默认为1。dilation可以用来增加卷积核的感受野,捕捉更大范围的上下文信息。 - groups:将输入和输出连接到一起的输入组和输出组的数量,默认为1。当groups大于1时,将使用分组卷积。 - bias:是否使用偏置项,默认为True。偏置项是可学习的参数,用于在卷积操作后添加一个常数偏移。 除了这些参数之外,nn.conv2d还有其他一些可选参数,如padding_mode(填充模式)、transposed(是否使用转置卷积)等,可以根据具体需求进行设置。 nn.conv2d函数的调用会返回一个卷积层对象,可以通过调用此对象的forward方法来进行卷积操作。输入张量会通过卷积核进行卷积计算,生成输出特征图。
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值