如何快速使用Python神经网络识别手写字符?

姓名:王咫毅

学号:19021211150

【嵌牛导读】在这个人工智能如日中天的时代,神经网络异军突起,成为人们研究的热点。如何自己动手搭一个神经网络的模型?使用python需要调用那些库?要识别一个手写体的数据集如何进行操作?这将是本文讨论的主要问题。

【嵌牛鼻子】mnist数据集 python 神经网络

【嵌牛提问】如何引用mnist数据集?使用什么样的神经网络可以识别率更高?

【嵌牛正文】

转载自:https://www.jianshu.com/p/f5ab24b24edb

点击标题下[异步社区]可快速关注

在本文中,我们将进一步探讨一些使用Python神经网络识别手写字符非常有趣的想法。如果只是想了解神经网络的基本知识,那不必阅读本文,可以先阅读《Python神经网络编程》前面2章节的内容。

这是一个有趣的额外部分,所以节奏会稍微加快一些,但是我们仍然尝试使用简单的语言来解释这些想法。

 1.1 自己的手写数字

在本文中,我们一直使用来自MNIST数据集的数字图片。为什么不使用自己的笔迹呢?

在这个实验中,我们将使用自己的笔迹创建测试数据集。我们也将尝试使用不同的书写风格,使用嘈杂或抖动的图片,来观察神经网络的应对能力如何。

你可以使用任何喜欢的图像编辑或绘画软件来创建图片。不必使用昂贵的Photoshop,GIMP是免费开源的替代软件,适用于Windows、Mac和Linux等系统。甚至可以用一支笔将数字写在纸上,并用智能手机、相机或任何合适的扫描仪,将手写数字变成图片格式。唯一的要求是图片为正方形(宽度等于长度),并且将其保存为PNG格式。在喜欢的图像编辑器中,保存格式选项的菜单通常为“File→Save As”或“File→Export”。

下面是我制作的一些图片。

​数字5就是我的笔迹。数字4是用粉笔而不是马克笔写的。数字3是我的笔迹并有意切成一段一段的。数字2是传统的报纸或书籍字体,但是进行了模糊处理。数字6有意做成抖动的样子,好像是在水中的倒影。最后一张图片与前面的数字相同,但是添加了噪声,来看看我们是否可以增加神经网络的工作难度。

虽然这很有趣,但是这里蕴含了很严肃的一点。人类大脑在遭受损害后,其能力依然能够得到良好发挥,科学家对此深感震惊。这暗示着,神经网络将它们所学到的知识分布在几条链接权重上,也就是说,如果若干链接权重遭受了一定损害,神经网络也可以表现得相当好。这同时意味着,如果输入图像被损坏或不完整,神经网络也可以表现得相当好。这是一种很强大的功能,这就是我们希望用上图中断断续续的3进行测试的能力。

我们需要创建较小的PNG图片,将它们调整到28个像素乘以28个像素,这样就可以匹配曾经用过的来自MNIST数据集的图片。你可以使用图像编辑器做到这一点。

Python库再次帮助了我们,它从常见的图像文件格式中(包括PNG格式)读取和解码数据。看看下面这段简单的代码:​

​scipy.misc.imread()函数帮助我们从图像文件,如PNG或JPG文件中,读取数据。必须导入scipy.misc库来使用这个函数。参数“flatten=True”将图像变成简单的浮点数数组,如果图像是彩色的,那么颜色值将被转换为所需要的灰度。

下一行代码重塑数组,将其从28×28的方块数组变成很长的一串数值,这是我们需要馈送给神经网络的数据。此前,我们已经多次进行这样的操作了。但是,这里比较新鲜的一点是将数组的值减去了255.0。这样做的原因是,常规而言,0指的是黑色,255指的是白色,但是,MNIST数据集使用相反的方式表示,因此不得不将值逆转过来以匹配MNIST数据。

最后一行代码是我们很熟悉的,它将数据值进行缩放,使得它们的范围变成0.01到1.0。演示读取PNG文件的示例代码可以在GitHub上找到:

·https://github.com/makeyourownneuralnetwork/makeyourownneuralnetwork/ blob/master/part3_load_own_images.ipynb

我们需要创建基本的神经网络,这个神经网络使用MNIST训练数据集进行训练,然后,不使用MNIST测试集对网络进行测试,而是使用自己创建的图像数据对网络进行测试。

在GitHub上,可通过如下链接获得新程序:

·https://github.com/makeyourownneuralnetwork/makeyourownneuralnetwork/ blob/master/part3_neural_network_mnist_and_own_data.ipynb

这样做成功了吗?当然成功了。下图总结使用我们自己制作的图像查询的结果。

​可以看到,神经网络能够识别我们创建的所有图像,包括有意损坏的数字“3”。只有在识别添加了噪声的数字“6”时失败了。

使用你自己的图像,尤其是手写的图像试试看,证明你的神经网络确实能够工作。

并且,仔细观察,要将图像损坏或变形到什么程度,神经网络才会失败。神经网络的弹性将会给你留下深刻的印象。

 1.2 神经网络大脑内部

在求解各种各样我们不知道如何使用简约明快的规则解决的问题时,神经网络发挥了重要作用。想象一下,写下一组规则,将这些规则应用于手写数字图像,来确定数字是什么,这件事并不是那么容易,并且我们的尝试也可能不会那么成功。

1.2.1 神秘的黑盒子

一旦神经网络得到了训练,并且在测试数据上表现良好,那么基本上你就拥有了一个神秘的黑盒子。你不知道这个黑盒子如何计算出答案,但是它确实成功地计算出了答案。

如果你只对答案感兴趣,而不真正关心它们如何得出这个答案的,那么对你来说,这就不是一个问题了。但是,我要指出这是这些机器学习方法类型的缺点,即虽然黑盒子(神经网络)已经学会如何求解问题,但是其所学习到的知识常常不能转化为对问题的理解和智慧。

让我们来看看是否可以到神经网络内部一探究竟,是否能够理解神经网络所学习到的知识,将神经网络通过训练搜集到的知识可视化。

我们可以观察权重,这毕竟是神经网络学习的内容。但是,权重不太可能告诉我们太多信息。特别是,神经网络的工作方式是将学习分布到不同的链接权重中。这种方式使得神经网络对损坏具有了弹性,这就像是生物大脑的运行方式。删除一个节点甚至相当多的节点,都不太可能彻底破坏神经网络良好的工作能力。

这里有一个疯狂的想法。

1.2.2 向后查询

在通常情况下,我们馈送给已受训练的神经网络一个问题,神经网络弹出一个答案。在我们的例子中,这个问题是人类的手写数字图像。答案是表示数字0到9中的某个标签。

如果将这种方式反转,向后操作,会发生什么呢?如果馈送一个标签到输出节点,通过已受训练的网络反向输入信号,直到输入节点弹出一个图像,那会怎么样?下图显示了正常的正向查询和疯狂的反向向后查询的想法。

​我们已经知道如何通过网络传播信号,使用链接权重调节信号,在应用激活函数之前在节点处重新组合信号。除了使用的是逆激活函数以外,所有这一切操作也都适用于反向传播信号。如果y= f(x) 是正向激活函数,那么这个函数的逆就是x= g(y)。使用简单的代数,求出逻辑函数的逆,也并非难事:

y= 1 / (1 + e-x)

1 + e-x = 1/y

e-x = (1/y) -1 = (1 -y) /y

-x = ln [ (1-y) /y]

x= ln [ y / (1-y) ]

这就是所谓的对数函数,就像Python为逻辑S函数提供scipy.special.expit()一样,Python中的scipy.special库也提供了这个函数,即scipy.special.logit()。

在应用逆激活函数logit()之前,我们需要确保信号是有效的。这是什么意思呢?还记得吧,逻辑S函数接受了任何数值,输出0和1之间的某个值,但是不包括0和1本身。逆函数必须接受相同的范围0和1之间的某个值,不包括0和1,弹出任何正值或负值。为了实现这一目标,我们简单地接受输出层中的所有值,应用logit(),并将它们重新调整到有效范围。我选择的范围为0.01至0.99。

这段代码在网上始终可用,请访问GitHub以获取:

·https://github.com/makeyourownneuralnetwork/makeyourownneuralnetwork/ blob/master/part3_neural_network_mnist_backquery.ipynb

1.2.3 标签“0”

来看看如果我们使用标签“0”进行反向查询,会发生什么情况。也就是说,我们向输出节点展示了一些值,除了使用值0.99展示给第一个节点表示标签“0”,其余节点都展示了0.01。换句话说,也就是数组[0.99, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01,0.01]。

下图显示了输入节点弹出的图像。

​这真是太有趣了!

这个图像让我们对神经网络的“大脑”有了一种深刻的见解。这个图像是什么意思?该如何解释这个图像呢?

我们注意到最主要的特征是,图像中的圆形。我们是在询问神经网络——对于答案“0”,最理想的问题是什么,因此,这个图像是有道理的。

我们也注意到深色、浅色和一些介中的灰色区域。

·深色区域是问题图像中应该使用笔来标记的部分,这部分图像组成了支持证据,证明答案为“0”,可以这样理解,这些部分看起来组成了0的形状轮廓。

· 浅色区域是问题图像中应该没有任何笔痕的部分,这支持了答案为“0”。同样,可以这样理解,这些部分形成了0形状的中间部分。

· 大体上,神经网络对灰色区域不是很敏感。

因此,粗略来讲,我们实际上已经理解了,针对如何将图像归类为标签“0”,神经网络已经学习到的知识。

这是一种难得的见解,对于较多层、较复杂的神经网络或较复杂的问题而言,可能没有如此容易解释的结果。我们鼓励你进行实验,亲自动手试一试。

1.2.4 更多的大脑扫描

下图显示了其他数字向后查询的结果。

​哇!同样是一些非常有趣的图像,就像使用超声波扫描神经网络的大脑一样。

关于这些图像,我们做了一些注解:

·“7”真的很清楚。可以看到在查询图像中标记的深色位置,强烈暗示了这是标签“7”。也可以看到额外的“白色”区域,这些区域没有任何标记。这两个特点结合起来,指示出了这是“7”。

· 这同样适用于数字“3”,有标记的深色区域指示出了“3”,白色的区域也非常清晰。

·“2”和“5”具有类似的清晰度。

· 数字“4”有点有趣,这个形状出现在4个象限中,是4个互相分隔的区域。

· “8”主要是由“雪人”构成的,这个“雪人”由白色区域形成,表明8的特征在于保持了“头部和身体”区的标记。

· 数字“1”令人相当费解。这看起来好像神经网络较多关注无需标记的区域,而较少关注需要标记的区域。没关系,这就是网络从样本中学到的知识。

· 数字“9”一点都不清楚。它有一个明确的深色区域,还有一些形状相对精细的白色区域。这就是神经网络所学习到的知识,总体来说,当与网络学会的其他数字结合时,这允许神经网络的表现达到了97.5%的准确度。我们观察一下这个图片,并得出结论,有更多的培训样本将有助于神经网络学到更清晰的“9”的模板。

现在,你对神经网络大脑的工作方式应该有了一个深刻的了解了吧。

 1.3 创建新的训练数据:旋转图像

如果思考一下MNIST训练数据,你就会意识到,这是关于人们所书写数字的一个相当丰富的样本集。这里有各种各样、各种风格的书写,有的写得很好,有的写得很糟。

神经网络必须尽可能多地学习这些变化类型。在这里,有多种形式的数字“4”,有些被压扁了,有些比较宽,有些进行了旋转,有些顶部是开放的,有些顶部是闭合的,这对神经网络的学习都是有帮助的。

如果我们能够创造更多的变化类型作为样本,会不会有用处呢?如何做到这一点呢?再多收集几千个人类手写数字样本,对我们来说有点不太容易。我们可以这样做,但是工作量有点大。

一个很酷的想法就是利用已有的样本,通过顺时针或逆时针旋转它们,比如说旋转10度,创建新的样本。对于每一个训练样本而言,我们能够生成两个额外的样本。我们可以使用不同的旋转角度创建更多的样本,但是,目前,让我们只尝试+10和-10两个角度,看看这种想法能不能成功。

同样,Python的许多扩展包和程序库都很有用。ndimage.interpolation.rotate()可以将数组转过一个给定的角度,这正是我们所需要的。请记住,由于我们将神经网络设计成为接收一长串输入信号,因此输入的是784长的一串一维数字。我们需要将这一长串数字重新变成28×28的数组,这样就可以旋转这个数组,然后在将这个数组馈送到神经网络之前,将数组解开,重新变成一长串的784个信号。

假设得到了先前的scaled_input数组,下列代码演示了如何使用ndimage.interpolation.rotate()函数:​

​可以看到,原先的scaled_input数组被重新转变为28乘以 28的数组,然后进行了调整。reshape=False,这个参数防止程序库过分“热心”,将图像压扁,使得数组旋转后可以完全适合,而没有剪掉任何部分。在原始图像中,一些数组元素不存在,但是现在这些数组元素进入了视野,cval就是用来填充数组元素的值。由于我们要移动输入值范围,避免0作为神经网络的输入值,因此不使用0.0作为默认值,而是使用0.01作为默认值。

小型MNIST训练集的记录6(第7条记录)是一个手写数字“1”。在下图中可以看到,原先的数字图片和使用代码生成的两个额外的变化形式。

​可以清楚地看到这种方式的好处。原始图像的版本旋转+10度,提供了一个样本,就像某些人的书写风格是将1向后倾斜。将原来图片的版本顺时针旋转10度更有趣。和原始的版本相比,这个版本在某种意义上是更具代表性的学习图片。

让我们创建新的Python Notebook,使用原来的神经网络代码,不过,现在我们将原始图片朝顺时针和逆时针两个方向旋转10度,作为额外的训练样本,来训练神经网络。这段代码在GitHub上可以得到,请访问以下链接:

·https://github.com/makeyourownneuralnetwork/makeyourownneuralnetwork/ blob/master/part2_neural_network_mnist_data_with_rotations.ipynb

设定学习率为0.1,并且只使用一个训练世代,初始运行神经网络,所得的性能是0.9669。这对于没有使用额外旋转图像进行训练的神经网络的性能0.954而言,是一个长足的进步。这样的表现,和列在Yann LeCeun网站中的记录相比也已经是名列前茅了。

让我们进行一系列的实验,改变世代的数目看看是否能够让已经不错的表现更上一层楼。现在,我们创建了更多的训练数据,可以采用更小、更谨慎的学习步长,因此将学习率减少到0.01,这样就总体上延长了学习时间。

请记住,由于特定的神经网络架构或训练数据的完整性,事情很可能存在内在的限制,因此我们不会期待得到98%或以上的准确度,或者甚至是100%的准确度。我们说“特定的神经网络架构”,意思是在每一层节点数目的选择、隐藏层的选择和激活函数的选择等。

我们旋转训练图像的角度,将其作为额外的训练样本,下图显示了在这种情况下的神经网络的性能。同时,下图也显示了没有使用额外旋转的训练样本时神经网络的性能,以便进行简单的比较。

​可以看到,在5个世代的情况下,最好的结果是0.9745或97.5%的准确度。这再一次打破了我们先前的纪录。

值得注意的是,如果旋转的角度过大,神经网络的性能会出现下降。由于旋转较大的角度意味着创建了实际上不能代表数字的图像,因此神经网络的性能出现了下降,这是可以理解的。想象一下,将“3”向一个方向旋转90度,这就不再是3了。因此,将过度旋转的图像添加到训练样本中,增加了错误样本,降低了训练的质量。对于最大化附加数据的价值,10度看起来是最佳角度。

在10个世代的情况下,神经网络的性能出现了峰值,打破了记录,达到了0.9787,几乎到达98%!对于这种简单的神经网络而言,这是一个惊人的结果,也是最佳的一种状态。请记住,有些人会对神经网络或数据进行一些巧妙的处理,我们还未这样做,我们只是保持简单的神经网络,但是却依然取得了令人骄傲的结果。

​做得好!

 1.4 结语

在本文中,我希望你已经明白,人类能够轻而易举解决的一些问题,对传统计算机而言却难以解决。图像识别就是这些所谓的“人工智能”的挑战之一。

神经网络使图像识别以及广泛的其他各类难题,都获得了空前的进步。求解这类难题的早期动力的一个关键性部分是生物大脑,如鸽子或昆虫的大脑,虽然这些生物大脑比起今天的超级计算机似乎简单一些,反应也较慢,但是它们依然能够执行复杂的任务,如飞行、喂食、建设家园。这些生物大脑对损害或对不完美的信号,也非常有弹性。数字计算机和传统计算却不能拥有这种能力。

今天,在人工智能中,神经网络是一些神奇的应用程序成功的关键部分。人们对神经网络和机器学习,特别是深度学习——也就是使用了有层次结构的机器学习方法,依然充满了巨大兴趣。在2016年年初,在古老的围棋对弈领域,谷歌的DeepMind击败了世界级大师。和国际象棋相比,围棋需要更深入的战略,更加微妙,研究人员原本以为计算机需要好几年的时间才能下得好围棋。因此,此次事件成为了人工智能史上一个巨大的里程碑。神经网络在计算机的成功中发挥了关键作用。

我希望你已经明白了,神经网络背后的核心思想其实是非常简单的。我希望你也可以从神经网络的实验中找到乐趣。也许,你已经有了探索其他类型的机器学习和人工智能的兴趣。

如果你做到了这些事情,那么我就算大功告成了。

本文摘自《Python神经网络编程》

​《Python神经网络编程》

 [英]塔里克·拉希德(Tariq Rashid) 著 

点击封面购买纸书

当前,深度学习和人工智能的发展和应用给人们留下了深刻的印象。神经网络是深度学习和人工智能的关键元素,然而,真正了解神经网络工作机制的人少之又少。本书用轻松的笔触,一步一步揭示了神经网络的数学思想,并介绍如何使用Python 3.5编程语言开发神经网络。

本书将带领您进行一场妙趣横生却又有条不紊的旅行——从一个非常简单的想法开始,逐步理解神经网络的工作机制。您无需任何超出中学范围的数学知识,并且本书还给出易于理解的微积分简介。本书的目标是让尽可能多的普通读者理解神经网络。读者将学习使用Python开发自己的神经网络,训练它识别手写数字,甚至可以与专业的神经网络相媲美。

本书适合想要了解深度学习、人工智能和神经网络的读者阅读,尤其适合想要通过Python编程进行神经网络开发的读者参考。

作者:人邮异步社区

链接:https://www.jianshu.com/p/f5ab24b24edb

来源:简书

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,179评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,229评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,032评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,533评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,531评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,539评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,916评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,813评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,568评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,654评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,354评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,937评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,918评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,152评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,852评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,378评论 2 342

推荐阅读更多精彩内容