这篇文章将为大家详细讲解有关如何用NumPy搭建卷积神经网络实现手写数字识别,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。
当Yann LeCun发表了他关于开发一种新型神经网络架构——卷积神经网络(Convolutional neural network, CNN)——的研究成果时,他的工作基本上没有引起注意。在2012年的ImageNet计算机视觉大赛上,来自多伦多大学的一组研究人员花了14年的时间将CNN引入公众视野。当他们从数千个类别的中对数百万张图片进行分类时,只产生了15.8%的错误。快进到现在,当前最先进的卷积神经网络实现的精度超过人类水平的性能。
ImageNet数据集上错误率
在这些有希望的结果的激励下,我开始了解CNN的功能,以及它们是如何表现得如此出色的。因此为了全面了解人工智能的这种进步,我在NumPy中从零开始构建了一个卷积神经网络。在完成这个项目之后,我觉得卷积神经网络在表面复杂性和它们实际复杂性之间存在着脱节。
CNN以其识别图像模式的能力而闻名,因此本文中描述的网络的任务就是图像分类。衡量计算机视觉算法执行情况的最常见基准之一是在MNIST手写数字数据库上对其进行训练:该数据库包含70,000个手写数字及其对应的标签。目标是训练CNN在标记手写数字(从0到9)时尽可能准确。经过大约5个小时的训练和在训练集上的两次循环,这里展示的网络能够在测试数据上达到98%的准确率,这意味着它可以正确地猜测显示给它的几乎每一个手写数字。
让我们回顾一下构成网络的各个组件,以及它们如何连接在一起,从输入数据形成预测。在解释了每个组件之后,我们将对其功能进行编码。在这篇文章的最后一部分,我们将使用NumPy对网络的每个部分进行编程和训练。废话少说,让我们开始吧。
卷积层(Convolutions)
CNN利用过滤器(也被称为内核)来检测图像中存在哪些特征,比如边缘。过滤器只是一个值的矩阵,叫做权值,它被训练来检测特定的特征。过滤器移动到图像的每个部分,检查它要检测的特征是否存在。为了提供一个值来表示特定特征的可信度,过滤器执行一个卷积操作,这是一个元素的乘积和两个矩阵之间的和。
当特征出现在图像的某一部分时,滤波器与该部分图像进行卷积运算,得到一个高值的实数。如果特性不存在,则结果值很低。
在下面的例子中,负责检查右边曲线的过滤器被传递到图像的一部分。由于图像的这一部分包含与滤波器所寻找的曲线相同的曲线,因此卷积运算的结果是一个很大的数(6600)。
但是,当相同的滤波器通过图像中具有相当不同的边缘集的部分时,卷积的输出很小,这意味着不存在很强的右手曲线。
为了使卷积神经网络能够学习检测输入数据中特征的滤波器的值,必须通过非线性映射来传递滤波器。滤波器与输入图像卷积运算的输出用偏置项求和,并通过非线性激活函数。激活函数的目的是将非线性引入到我们的网络中。由于我们的输入数据是非线性的(对形成手写签名的像素进行线性建模是不可行的),我们的模型需要考虑这一点。
代码要点:
使用NumPy,我们可以很容易地对卷积运算进行编程。卷积函数利用for循环对图像上的所有过滤器进行卷积。在for循环的每个迭代中,使用两个while循环将过滤器传递给图像。在每个步骤中,过滤器是多元素的(*)与输入图像的一部分。然后使用NumPy 's sum方法将这个元素相乘的结果求和,得到一个单独的值,然后添加一个偏差项。
缩减像素采样(Downsampling)
为了加快训练过程并减少网络消耗的内存,我们尝试减少输入特性中存在的冗余。有几种方法可以对图像进行降采样,但在这篇文章中,我们将着眼于最常见的一种:max pooling(最大池化)。
在最大池化中,一个窗口根据设定的步长(每次移动多少单位)从一个图像上经过。在每个步骤中,窗口内的最大值被合并到一个输出矩阵中,因此称为最大池化。
在下面的图像中,大小为f=2的窗口以2的步长通过图像。f表示最大池化窗口的大小(红色框),s表示窗口在x和y方向上移动的单元数。在每个步骤中,选择窗口内的最大值:
最大池化极大地减少了表示大小,从而减少了所需的内存数量和以后在网络中执行的操作数量。
代码要点:
最大池操作归结为一个for循环和几个while循环。for循环用于遍历输入图像的每一层,while循环将窗口滑动到图像的每个部分。在每个步骤中,我们使用NumPy的max方法来获得最大值
全连接层(fully-connected layer)
在神经网络的全连通操作中,输入表示被压扁成一个特征向量,并通过神经元网络来预测输出概率。
这些行被连接起来形成一个长特征向量。如果存在多个输入层,则将其行连接起来形成更长的特征向量。
然后将特征向量通过多个密集层。在每一稠密层,特征向量乘以该层的权值,加上它的偏差,然后通过非线性。下图显示了全连通操作和稠密层:
代码要点:
NumPy使得编写CNN的全连接层变得非常简单。事实上,你可以用NumPy的reshape方法在一行代码中完成
输出层(Output layer)
CNN的输出层负责生成给定输入图像的每个类(每个数字)的概率。为了获得这些概率,我们初始化最后的致密层,使其包含与类相同数量的神经元。然后,这个稠密层的输出通过Softmax激活函数,该函数将所有最终的稠密层输出映射到一个元素之和为1的向量。
经过训练,网络在测试集上的准确率平均为98%,我认为这是相当不错的。将训练时间延长2-3个epoch后,我发现测试集的性能下降了。我推测,在第三到第四个训练循环中,网络开始过度拟合训练集,不再泛化。
关于如何用NumPy搭建卷积神经网络实现手写数字识别就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。