AI入门:神经网络实战----卷积神经网络

前言
我们使用的MNIST数据集中的数据大体是这样的:有效的像素只占据28 * 28个像素中的很小一部分。另外,即使是有效的像素之间,它们也不一定有联系,一般来说,一个像素点只会跟它附近的像素有联系,与比较远的像素没有联系。

在这里插入图片描述

上一节,我们使用全连接把输入层与第二层相连接,单单这一层的连接数就有784 * 256 = 20万个。这个数据是比较大的,事实上也是非常浪费的。如果我们能够把这些有效像素提取出来,则我们减少大量计算,同时提高准确率。再进一步,其实我们可能只需要知道几个点,就可以判断这个图像表示什么数字,而没有必要了解所有点的情况,这样就可以进一步提高运行速度和准确率。
什么是卷积,为什么要卷积
卷积是一个数学概念,表示两个多项式A(x)和B(x)的每个元素相乘之后再累加的结果。把卷积操作应用到神经网络中就是卷积神经网络。以下图为例,原始图片上3 * 3的数据,与3 * 3的卷积核发生卷积操作之后,只生成了一个数据。这样相当于把9个数据变成一个数据了,极大的减少了数据量。换一种思路就是我们可以通过卷积操作提取到原始图片中的关键特征。不过这样就会产生一个问题:怎么保证提取到的特征是真正需要的特征呢?
关于这个问题,其实没有好的方法,目前通用的解决方案是换不同的卷积核,多卷积几次。这样可以保证把需要的特征都提取出来。这种方案的问题是可能会重复提取特征。从下图可以看到,如果把原始图片中的数据看做是一个3 * 3的矩阵,卷积核也看做是一个3 * 3的矩阵,这个卷积操作其实就是矩阵的乘法运算,最后再把生成的矩阵中的所有元素都累加得到结果。这个过程在GPU中计算特别快,另外,由于卷积神经网络中有80%的工作都是在做卷积操作,因此强烈建议在GPU中训练卷积神经网络。

在这里插入图片描述
经过卷积操作之后,我们可以把图片的特征压缩到比较小的程度,但是我们可以进一步通过池化操作减少数据量。所谓池化就是2 * 2的元素中进行四选一,或者更进一步,使用3 * 3的元素中进行九选一。池化有最大池化和平均池化两种方式,我们一般选用最大池化。也就是在4个元素中挑选最大的那个。通过池化可以减少75%的数据量。

在这里插入图片描述

通过上述卷积和池化操作之后,我们发现一张图片被转化成很多张小图片了。这些小图片中存放的就是提取出来的特征。对于单次计算而言,计算量急剧下降。但是由于有很多小图片,所以总体的计算量是增加很多的。
卷积相关函数
卷积的函数:nn.Conv2d(input, output, kernel_size, padding=0, stride = 0)
input:输入的图片的channel数。这里输入的是MNIST数据集,是灰度图,所以是channel数为1。
output:输出的channel数。这个数据是程序员确定的,建议是2^n。
kernel_size:卷积核的大小,一定要是奇数,这里选择5。注意,卷积核的长和宽是相等的。 padding:卷积核移动的时候,原图片的像素可能不够用,所以要补充一些像素,这些像素的值都是0,这样就不会对原来的结果产生影响。padding的默认值为0。
stride默认为1,也就是卷积核每次移动一个像素。
其它:bias=True,表示使用bias。

最大池化的函数:F.max_pool2d(input, (2, 2))
input就是卷积 (并且激活) 后的数据,(2, 2)表示从2*2的数据中挑选最大的那个元素。

值得注意的是,卷积神经网络提取特征的能力很强,而且特征容易被重复提取。所以相当于神经网络被反复训练,这样就会导致这个神经网络对训练数据的预测效果很好,但对测试数据的预测效果不好。根本原因是这个神经网络已经记住了训练数据,而不是“识别”出来。专业术语称之为“过拟合”。为了解决过拟合的问题,现在主要有L1、L2正则化、dropout等三种方式。其中效果最好的是dropout。
dropout的函数:input = F.dropout(input, p, training)。
p是参数的保留率,一般是0.5~0.8之间的一个数。dropout的输出结果与输入数据的形状相同。
编写卷积神经网络,计算图片尺寸、参数量
我们可以看到,卷积操作时,图片是被当作一个矩阵看待的,而不像全连接层时作为一维数据看待。由于图片是需要考虑通道数的 (灰度图的通道数为1,彩色图为3)。所以,在做卷积操作时,一定要保证输入数据的格式为: (BATCH_SIZE, channels, width, height)。MNIST数据集中的数据是被处理成(28, 28)的,所以在做卷积操作之前要变换一下张量的形状。
当卷积完成之后,我们还需要进行两次全连接操作。全连接的输入数据是一维的,所以在卷积完成后需要再改变一下形状。
下面我们计算一下卷积前后特征图片的尺寸。在卷积之前,图片的尺寸是(28, 28)。如果我们的卷积核的尺寸是(5, 5),每次移动一步。则卷积之后的图片的宽度为:28 - 5 + 1 = 24。用这种方式进行卷积的话,经过多次卷积,图片尺寸会变得越来越小。那么有什么办法让卷积得到的图片不变小 (与原始图片保持一样的尺寸) 呢?这时我们就需要在图片四周填充一些没有信息的空白像素。我们发现卷积之后图片的宽度小了4,所以我们应该在图片两侧各填充2个像素。这个操作的专业术语称之为:padding。
卷积之后图片的宽度的计算公式:width2 = (width + 2 * padding - kernel_size)/stride + 1。反过来,如果我们知道卷积前后的图片的尺寸,也可以推导出计算padding的公式:padding = ((width2 -1) * stride - width + kernel_size) / 2。

下面是卷积的代码:
首先在__init__()中定义两个卷积层,然后是三个全连接层,最后输出预测结果。
这里输入的是MNIST数据集,是黑白图片,所以是channel数为1。所以第一层的Conv2d()中第一个参数是1。第二个参数6是程序员指定的,表示输出的channel数,第三个参数5表示卷积核的大小。这里使用padding = 2,所以卷积之后的图片的宽度 = 高度 = (28 + 2 * 2 - 5) / 1 + 1 = 28,也就是卷积前后图片的尺寸保持不变。这个卷积层的参数量是:1 * 6 * 5 * 5 = 150个。紧接着这个卷积层,后面有一个(2, 2)的池化层,使得图片的尺寸变为(14, 14)。

第二层的Conv2d()参数也是类似。第一个参数6就是上一层卷积产生的6层的图片,第二个参数16是程序员指定的,表示输出的channel数,第三个参数5表示卷积核的大小。这里使用padding = 0,所以卷积之后的图片的宽度 = 高度 = (14 + 2 * 0 - 5) / 1 + 1 = 10,也就是卷积之后图片的尺寸变为(10, 10)。这个卷积层的参数量是:6 * 5 * 5 * 16 = 2400个。紧接着这个卷积层,后面有一个(2, 2)的池化层,使得图片的尺寸变为(5, 5)。

在完成上述卷积、池化操作后,我们要把这些图片输入到三层全连接层。这时我们一共有16张图片,每张图片的尺寸是(5, 5),所以一共有16 * 5 * 5 = 400个特征。第一个全连接层的神经元一共有128个,所以这两层之间的参数有16 * 5 * 5 * 128 = 51200个 (只考虑w,不考虑b)。
第二层全连接的参数数量为:128 * 64 = 8192个。
第三层全连接的参数数量为:64 * 10 = 640 个。
我们可以看到,总的参数量为:150 + 2400 + 51200 + 8192 + 640 = 62582个,其中卷积层与第一个全连接层之间的参数占据了81.8%,(只考虑w,不考虑b)。

在这里插入图片描述

在定义完各个层的参数之后,就是编写forward()函数:forward()中各层的代码是非常简单的,就是一层一层累加上去即可。
这里需要注意三点:
① 卷积、激活、池化、dropout这四个操作的次序不要弄乱;
② 卷积完成后要先把图片数据转成一维的。这时一定要明确的指出各个参数,不能让PyTorch自动计算。
③ 全连接层的最后的输出不需要激活,也不需要softmax。

在这里插入图片描述

定义完模型后要实例化一个模型的变量,接着指定优化器、学习率、以及损失函数的计算公式。这些与上一节的全连接的神经网络一样。

在这里插入图片描述

卷积神经网络的训练和测试
卷积神经网络的训练和测试与上一节的全连接的神经网络一样。这里就不重复写了。
在训练的时候,我们发现如果给定一个比较大的batch_size,则有可能导致占用内存很大。如果使用的是CPU进行训练,且内存占用率超过总的内存大小,则系统直接死机。如果使用的是GPU,则报错 (但不死机)。用CPU训练全连接的神经网络速度是比较快的,但是训练卷积神经网络就非常慢了,使用GPU可以大大加速训练过程。当然,使用CPU和GPU得到的结果是一样的。
经过5个epochs的计算,卷积神经网络的准确率可以达到97%,比全连接的神经网络高约2%。增加epochs到20,最终可以达到98%以上的准确率。
总结
这一节里,我们提出了使用全连

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值