机器学习实战篇——神经网络实现手写数字识别

介绍:

今天我们来进入实战阶段,学习一门技能不仅要懂理论更要实际操作,刻意练习才会有效果,机器学习更是这样。

准备工作:

1. 安装jupyter notebook, 教程:http://codingpy.com/article/getting-started-with-jupyter-notebook-part-1/

2. 一台配置高点的电脑,这个还是有必要投入一些的,不然每次做练习都要等上很长时间,我在公司的电脑大概做完这个训练要10秒左右,回家后的电脑要130秒左右。这还是一次训练的时间,后面做优化还需要训练超参数与多种模型对比,总不能每次都多等待10几倍的时间吧,程序员最忍受不了的就是无效的等待时间。

机器学习实战篇——神经网络实现手写数字识别

CPU: intel core i7-7700k 4.4G

内存:4X8G

显示卡: 两个NV GTX 1070

硬盘: HDD一个, SSD两个

这里多唠两句嗑儿,在技术装备上千万不要舍不得花钱,用2万多的电脑去学习心态都不一样,心里会想“这么贵的电脑,要多用几次啊,不能闲置在那儿浪费了,多做练习,多码代码”,多练习恰恰就是你是否能学习成功的关键,要用任务去驱动自己,积极主动的去学习。要记住一点,现在花的钱以后都会十倍,百倍的挣回来。 (当然我不是推销卖电脑的,只是传达一种理念)

引用:

我们要用到的是Michael Nielsen的例子,github地址:https://github.com/mnielsen/neural-networks-and-deep-learning

采用的数据集就是著名的“MNIST数据集”。它的收集者之一是人工智能领域著名的科学家——Yann LeCu。这个数据集有60000个训练样本数据集和10000个测试用例。运用本文展示的单隐层神经网络,就可以达到96%的正确率。

举例:

首先回顾一下机器学习的过程:

  • 选择数据

  • 训练模型

  • 测试模型

  • 调优模型

用一张图片来表示

机器学习实战篇——神经网络实现手写数字识别

其中生成模型这一步非常重要,它并不是一下就生成好了,是调整神经网络的权重和偏移,取训练中误差非常低的那个,这里就联系到之前讲的“最小二乘法”的相关概念。

注意训练集的数据会反复用,但是测试集的数据只会执行一次。可能会生成多个模型误差都很小,这时候就用测试集来比较,挑选出测试集误差最小的模型。

代码:

不要紧张老铁,代码总共5行,还是算上两行import的代码的情况下。

import mnist_loader

import network

training_data, validation_data, test_data = mnist_loader.load_data_wrapper()

net = network.Network([784, 30, 10])

net.SGD(training_data, 30, 10, 3.0, test_data=test_data)

解释一下:

  • 第一行代码:将数据集拆分成三个集合:训练集、交叉验证集、测试集。

  • 第二行代码:生成神经网络对象,神经网络结构为三层,每层节点数依次为(784, 30, 10)。

  • 第三行代码:用(mini-batch)梯度下降法训练神经网络(权重与偏移),并生成测试结果。

  • 该命令设定了三个超参数:训练回合数=30, 用于随机梯度下降法的最小样本数(mini-batch-size)=10,步长=3.0。

什么是超参数呢?超参数是影响所求参数最终取值的参数,是机器学习模型里面的框架参数,可以理解成参数的参数,它们通常是手工设定,不断试错调整的,或者对一系列穷举出来的参数组合一通进行枚举(网格搜索)来确定。

打开jupyter notebook进入到下载的github代码文件夹,再进入src的文件夹,创建一个空白的python2.7的notebook,把代码一个字一个字的打进去,打的时候想想上面的注释内容,千万别粘贴,丢面儿,就5行代码而已。打完后直接运行就可以看到输出结果,下面是我刚打的,热乎乎:

机器学习实战篇——神经网络实现手写数字识别

启发式理解

机器学习实战篇——神经网络实现手写数字识别

  • 第一层是输入层。因为mnist数据集中每一个手写数字样本是一个28*28像素的图像,因此对于每一个样本,其输入的信息就是每一个像素对应的灰度,总共有28*28=784个像素,故这一层有784个节点。

  • 第三层是输出层。因为阿拉伯数字总共有10个,我们就要将样本分成10个类别,因此输出层我们采用10个节点。当样本属于某一类(某个数字)的时候,则该类(该数字)对应的节点为1,而剩下9个节点为0,如[0,0,0,1,0,0,0,0,0,0]。

  • 因此,我们每一个样本(手写数字的图像)可以用一个超长的784维的向量表示其特征,而用一个10维向量表示该样本所属的类别(代表的真实数字),或者叫做标签。

  • mnist的数据就是这样表示的。所以,如果你想看训练集中第n个样本的784维特征向量,直接看training_data[n][0]就可以找到,而要看其所属的标签,看training_data[n][1]就够了。

  • 那么,第二层神经网络所代表的意义怎么理解?这其实是很难的。但是我们可以有一个启发式地理解,比如用中间层的某一个节点表示图像中的某一个小区域的特定图像。这样,我们可以假设中间层的头4个节点依次用来识别图像左上、右上、左下、右下4个区域是否存在这样的特征的。

机器学习实战篇——神经网络实现手写数字识别

如果这四个节点的值都很高,说明这四个区域同时满足这些特征。将以上的四个部分拼接起来,我们会发现,输入样本很可能就是一个手写“0”!

机器学习实战篇——神经网络实现手写数字识别

因此,同一层的几个神经元同时被激活了意味着输入样本很可能是某个数字。

当然,这只是对神经网络作用机制的一个启发式理解。真实的过程却并不一定是这样。但通过启发式理解,我们可以对神经网络作用机制有一个更加直观的认识。

总结:

通过今天的5行代码,可以算是自己在机器学习界的 “Hello world”。重点是理解机器学习的工作流程,以及神经网络作用机制。


分享到:


相關文章: