第三节:卷积层详解2
Posted 快乐江湖
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第三节:卷积层详解2相关的知识,希望对你有一定的参考价值。
文章目录
一:感受野
(1)从神经科学中获得灵感
1958年,神经科学家通过对小猫进行实验,观察猫的脑内神经元是如何响应投影在猫前方屏幕上的图像。实验表明,小猫脑内的每个单个神经元只对特定的图像特征有反应,比如有些神经元会被图像中横向的边缘所激活,另一些神经元则被纵向的或者对角方向的边缘所激活,而还有些神经元对亮光带和暗光带的反应模式也不相同。
这说明,单个神经元的作用域并不是整个图像,而只是图像的一个子集,这个子集就叫做感受野(Receptive Field)。相邻的神经元有着相似的,相互重叠的感受野,所有神经元有序的组织起来共同形成对图像的认知
另外,他们还在研究中发现,视觉系统的信息处理是分层的
(2)神经网络中的感受野
它是指神经网络中神经元“看到的”输入区域,在卷积神经网络中,特征图上某个元素的计算受输入图像上某个区域的影响,该区域即该元素的感受野
如下,卷积层中不同的神经元指的并不是不同的卷积核,而是作用域不同感受野的相同卷积核。看一看出其训练的次数大大降低
对于卷积神经网络而言,利用卷积核与输入特征之间的互相关操作提取特征(卷积),输出特征中的每一个元素由卷积核在输入特征上的一次移动得到,而卷积核的每次移动均是与输入中与之对应的局部区域进行运算,既输出中的每个元素只由输入中的局部区域影响,此处所说的局部区域的大小感受野
- 如下图,可看到输出中的每个元素都由(3,3)的卷积核对应输入中(3,3)的局部区域“加权求和”得到,所以该输出的特征元素对应到输入中的区域大小就是3×3,既其感受野大小为3×3
(3)感受野深刻理解
- 下面的例子中所有卷积核大小均为:(3,3)
原始输入(3,3),共经历1个卷积层:此时,唯一的卷积层输出结果为(1,1),输出特征仅含有一个元素,而该元素对应输入中的3×3区域,故其感受野为3×3
原始输入(5,5),共经历2个卷积层:此时,第一个卷积层输出结果为(3,3),而第二个卷积层输出为(1,1)。第二层的输出仅有一个元素,该元素是由第一层输出结果中(3,3)特征得到;而对于第一层输出结果而言,其中的每一个元素的感受野是3×3,所有元素是通过原始输入中的(5,5)区域映射而来,所以对于第二层输出结果来说其元素的感受野为(5,5)
原始输入O(7,7),共经历3个卷积层:此时三个卷积层的输出依次为A(5,5),B(3,3)和C(1,1)。对于C而言,仅有一个元素,是由B中3×3区域得到;对于B而言,每个元素由A中(3,3)区域得到,所有元素由A中(5,5)区域得到;对于A而言,每个元素由原始输入O中(3,3)区域得到,所有元素由O中(7,7)区域得到,A中一个(3,3)区域的特征由O中(5,5)特征映射而来,所以对于三个卷积层的输出结果A、B、C来说,感受野依次为(3,3)、(5,5)、(7,7)
由上面的例子也可以看到通常情况下,网络越深,输出的结果所拥有的感受野越大。 所以对于当前层的输出结果,要看其感受野多大可通过以下方式:从当前层的输出结果反向映射,直到映射回原始输入特征,此时即可得到对应的感受野大小。比如上图中的第三层结果C,C由中的元素由B中的3×3区域得到,B中的3×3区域需要A中的5×5区域得到,而A中的5×5区域由原始输入中的7×7区域得到,所以对于C中元素而言,其感受野大小为7×7
二:步长和零填充
(1)步长
步长(stride):在滑动卷积核的时候必须指定步长,当步长为1时将会每次移动1个像素,当步长为2时将会每次移动2像素,当然也可以是其他数字
(2)零填充
零填充(zero-padding):零填充的存在就是为了防止在卷积中出现越界。例如4×4的矩阵用3×3的卷积核滑动,步长为2,会发现滑动到下一个窗口时,越界
此时我们会以0填充
三:三维卷积
在实际应用中我们都是对多维的矩阵进行卷积操作,例如一张RGB图像,有3个通道,所以我们需要使用3个卷积核
与二维卷积类似,我们会在水平方向上滑动卷积核,每次移动时,将获取整个图片三个通道的加权平均值,也即RGB的加权领域,由于我们仅在两个维度上滑动,所以得到是以二维矩阵
四:卷积后维度计算
经过卷积运算后维度计算公式为
- p p p:零填充数目
- s s s:步长
- n n n:输入
- f f f:卷积核函大小
n − f + 2 p s + 1 \\fracn-f+2ps+1 sn−f+2p+1
例如输入为6×6,卷积核大小为3×3,不做零填充,步长为1,则卷积后维度为4×4。可以看到padding前面的系数是,所以在padding时,一般会左右各padding一列或上下各padding一行。但问题是,如果stride变为了2,而分子上面算出来是奇数怎么办,这导致最后的结果成了小数,解决方法也很简单,TensorFlow中会补一行0在下面或补一列在右面。但是在pytorch中它会四周都补充
- 下面显示的是0.9862而并非0,是因为pytorch会在卷积之前补0,这里的0.9862是偏置值
所以我们在nn.Conv2d中填写padding时,一般会写成 “kernel_size//2”
五:只有一个卷积层吗
前面说过,世界神经系统是分级的
- 大脑皮层V1区的视觉神经元只能提取出一些零散的边缘特征
- V2区的神经元在V1区神经元的输出的基础上得到了一些基本形状信息
- V4区的神经元又在V2区神经元的输出的基础上得到了更高级别的形态信息
卷积神经网络也是同样,第一层卷积层由于感受野较小,往往以得到一些基本边缘信息为主要目的,比如横向边缘,纵向边缘,较短小的圆弧等。而第二层卷积层基于第一层卷积层的输出,便可以得到这些边缘信息的组合情况,比如是否匹配长方形,是否有半圆形状等,以此类推,卷积层越多,最终会得到越复杂的特征信息
六:深度学习框架如何实现卷积运算
(1)运算过程
如下是一个卷积操作,将一个4×4的输入通过3×3的卷积核进行普通卷积后,会得到2×2的输出
Pytorch在实现卷积运算时是通过矩阵相乘实现的,例如上例,首先需要把这个3×3的卷积和变换为4×16的矩阵,之所以这样变换的原因是因为
- 对于4×4的输入而言,卷积核一共要移动四次,所以我们把输入看成一维的向量,就有16个元素
- 当单个卷积核运算时,只涉及9个元素,另外7个元素无效,所以要补充为0
如下,把4×4的输入展开为一维,然后进行卷积操作
运算完毕后再reshape即可
(2)torch.nn.Conv2d
torch.nn.Covn2d
:对由多个输入平面组成的输入信号进行二维卷积
torch.nn.Conv2d(
in_channels, # 输入图像通道数
out_channels, # 卷积产生的通道数,也即你要定义多少个卷积核
kernel_size, # 卷积核尺寸;2表示2×2
stride, # 卷积步长,默认为1
padding, # 填充操作,控制padding_mode的数目
padding_mode, # padding模式,默认为零填充
dilation, # 空洞卷积
groups, # 分组卷积
bias, # 默认为True,表示在输出中添加一个可学习的偏差
)
举例
import torch
from torchvision import transforms
import cv2 as cv
transform = transforms.Compose(
[transforms.ToTensor(),
]
)
image = cv.imread('./image/HSB.png')
RGB = cv.cvtColor(image, cv.COLOR_BGR2RGB)
print(RGB.shape)
# 转换位tensor后,维度为C H W
X = transform(RGB)
print(X.size())
# 增加batch_size维度 C H W -> N C H W
X = X.unsqueeze(0)
print("bach_size:, channels:, height:, width:".format(X.shape[0], X.shape[1], X.shape[2], X.shape[3]))
KERNEL_SIZE = 5
Conv2d_layer = torch.nn.Conv2d(
in_channels=3, # 输入通道数为3
out_channels=32, # 32个卷积核
kernel_size=KERNEL_SIZE, # 卷积核大小
stride=1, # 步长为1
padding=(KERNEL_SIZE//2, KERNEL_SIZE//2) # padding
)
out = Conv2d_layer(X)
print("bach_size:, channels:, height:, width:".format(out.shape[0], out.shape[1], out.shape[2], out.shape[3]))
以上是关于第三节:卷积层详解2的主要内容,如果未能解决你的问题,请参考以下文章
原创 深度学习与TensorFlow 动手实践系列 - 3第三课:卷积神经网络 - 基础篇