PyTorch入门实战教程笔记(十九):卷积神经网络CNN 1
什么是卷积
1. 卷积神经网络基本概念
对于神经网络有几层,第一层为输入层,是不计算在内的,下图有3个隐藏层1个输出层,所以是4层的神经网络。每一层包含输入它的参数和它的输出。对于MiNIST数据集,2828 输入为784,参数一共390k,1.6M存储。
但是虽然1.6M存储,在当时储存计算也是非常困难的,计算机学家就利用模仿人眼的一个局部相关性,提出的网路叫做卷积神经网络,卷积指的是局部相关性,每次感受的是小的视野,而且小窗口会移动,且权值是共享的,能够大大减少参数量。卷积操作解释可参考:深度学习之CNN入门:1.卷积神经网络,简单的说,图像中的卷积操作就是利用卷积核在图片上按照一定步长进行滑动,并将对应位置进行点成运算,然后将点成运算结果累加成一个数值,即为下一个feature map的点。
2. 卷积神经网络
首先我们来看一下,对于2D的图片数据,是怎么进行卷积运算的,假设图像数据为I(x,y),卷积核kernel为k(x,y),卷积核是什么类型的就会生成什么类型的数据,比如,边缘,模糊等; 生成的数据feature map为F(x,y),然后按照卷积公式运算,对于离散数据来说,积分等于累加和。此外,可以算出对于2828的图片,经过33的卷积核卷积之后,F的尺寸为2626,如下图。(这个运算其实是有公式的,随后讲)。
下面动图演示了卷积的具体操作,黄色卷积核在图像上滑动计算先点乘、再累加和,得到的矩阵(粉色矩阵) ,即feature map:,修改滤波矩阵,可进行边缘检测、锐化和模糊等操作;滤波器越多,提取到的图像特征就越多,网络所能在未知图像上识别的模式也就越好。具体的关于卷积核(kernel)、步长(stride)、池化(padding)等操作详解,可参考:吴恩达deeplearning之CNN—卷积神经网络入门
下面我们看一个更加常见的情况:RGB图像的卷积处理。输入x为:[b,3,28,28], 其中b为Batchsize,为RGB,2828为图片大小,卷积核 one k:[3, 3,3], 整个卷积核叫一个kennel,第一个3对应于RGB,后俩个3为卷积核的大小(是可以自己选择的,33,55,77都可以)。如果多个kennels的话 如;[16, 3, 3, 3],为16个kennels,后面的3和前面叙述的含义相同,其中偏置b的shape与之对应为[16],最后输出为[b, 16, 28, 28].(有padding)。看下图具体的彩色图片卷积操作,红色和粉色为分别为一个kennel的卷积核,以红色卷积核为例:计算过程为每个kennel的3个卷积核和对应的RGB通道进行卷积,卷积得到的3个数值在累加和,得到一个数值对应于最右边第一个图的一个元素,完成一次卷积操作。然后通过相应的步长来一个一个卷积,最终生成最右边第一个图(feature map)。
卷积神经网络实现
那么 怎么使用pytorch来实现卷积的过程呢,可以用nn.Conv2d()函数来实现,以下图第一行代码为例,第一个参数为input的channel:1(即输入灰度图像为[b, 1, 28, 28],假设b为1),第二个参数指kennel的数量3,第三个参数为kernel_size为3(即3个1维的33的卷积核),第四个参数为步长stride:1,第五个参数为padding:0。设置好后,调用layer.forward()函数(注意: pytorch推荐使用实例的方法,即倒数第二行的layer(x),其实调用的是 .__call__函数,pytorch在 __call__函数中封装了一些hooks,hooks里面有很多高级操作,如果使用layer.forward()就无法实现hooks的实现。),就完成了一次卷积的前向运算,得到的out为1张图片,3个通道,大小为2626,下面几行代码更改stride和padding的参数的效果,具体如下图:
刚刚通过nn.Conv2d(),可以通过layer.weight, 可以看权重的参数,会发现requires_grad = True,意味着我们在做训练的时候,会自动的更新。如下:
除此之外,也可以用F.conv2d来实现卷积操作,要注意,权重w的shape和输入x的shape要相对应,比如输入x为[1, 1, 28, 28]而w为[16,3,5,5],就不对应,就会报错。
池化层与采样
- 下采样(downsample)
max pooling:
以一定步长移动一个窗口,然后取窗口内的最大值,如下图:
Avg pooling
以一定步长移动一个窗口,然后取窗口内的平均值,如下图:
使用pythorch操作,nn.MaxPool2d(),第一个参数为窗口大小,第二个参数为窗口移动步长。F.avg_pool2d(),第一个参数为x,第二个参数为为窗口大小,第三个参数为窗口移动步长。 - 上采样(upsample)
使用pythorch操作,F.interpolate(),第一个参数为x,第二个参数为方法的倍数,第三个参数为mode模数,如双线性,三线性差值,近邻差值等等,下图代码使用近邻差值。
ReLU
在训练神经网络的时候,一个单元一般由 conv2d,Batch,pooling,relu等,具体怎么搭配,取决于自己。再具体实现,可以用nn.ReLU(inplace = True),将inplace设置为True,能够节约内存的消耗,也可以用F.relu(x).运算前后tensor的shape不变。