如何从代码的角度解读深度学习
扫描二维码
随时随地手机看文章
在本文中会站在代码的角度上为你解读深度学习的前世今生,文章根据六段代码从不同的阶段解说,并将相关的代码示例都上传展示了。如果你是FloydHub新手,在本地计算机上的示例项目文件夹中安装好CLI之后,可以使用以下命令在FloydHub上启动项目:
接下来我们一起跟着原作者细读这六段极富历史意义历史的代码,最小二乘法
最小二乘法最初是由法国数学家勒让德(Adrien-Marie Legendre)提出的,他曾因参与标准米的制定而闻名。勒让德痴迷于预测彗星的位置,基于彗星曾出现过的几处位置,百折不挠的计算彗星的轨道,在经历无数的测试后,他终于想出了一种方法平衡计算误差,随后在其1805年的著作《计算慧星轨道的新方法》中发表了这一思想,也就是著名的最小二乘法。
勒让德将最小二乘法运用于计算彗星轨道,首先是猜测彗星将来出现的位置,然后计算这一猜测值的平方误差,最后通过修正猜测值来减少平方误差的总和,这就是线性回归思想的源头。
在Jupyter notebook上执行上图的代码。 m是系数,b是预测常数,XY坐标表示彗星的位置,因此函数的目标是找到某一特定m和b的组合,使得误差尽可能地小。
这也是深度学习的核心思想:给定输入和期望输出,寻找两者之间的关联性。
梯度下降
勒让德的方法是在误差函数中寻找特定组合的m和b,确定误差的最小值,但这一方法需要人工调节参数,这种手动调参来降低错误率的方法是非常耗时的。在一个世纪后,荷兰诺贝尔奖得主彼得·德比(Peter Debye)对勒让德的方法进行了改良。
假设勒让德需要修正一个参数X,Y轴表示不同X值的误差。勒让德希望找到这样一个X,使得误差Y最小。如下图,我们可以看出,当X=1.1时,误差Y的值最小。
如上图,德比注意到,最小值左边的斜率都是负数,最小值右边的斜率都是正数。因此,如果你知道任意点X值所处的斜率,就能判断最小的Y值在这一点的左边还是右边,所以接下来你会尽可能往接近最小值的方向去选择X值。
这就引入了梯度下降的概念,几乎所有深度学习的模型都会运用到梯度下降。
假设误差函数 Error = X5 - 2X3 - 2
求导来计算斜率:
如果读者需要补充导数的知识,可以学习Khan Academy的视频。
下图的python代码解释了德比的数学方法:
上图代码最值得注意的是学习率 learning_rate,通过向斜率的反方向前进,慢慢接近最小值。当越接近最小值时,斜率会变得越来越小,慢慢逼近于0,这就是最小值处。
Num_iteraTIons 表示在找到最小值前估算的迭代次数。
运行上述代码,读者可以自行调参来熟悉梯度下降。
线性回归
线性回归算法结合了最小二乘法和梯度下降。在二十世纪五六十年代,一组经济学家在早期计算机上实现了线性回归的早期思想。他们使用穿孔纸带来编程,这是非常早期的计算机编程方法,通过在纸带上打上一系列有规律的孔点,光电扫描输入电脑。经济学家们花了好几天来打孔,在早期计算机上运行一次线性回归需要24小时以上。
下图是Python实现的线性回归。
梯度下降和线性回归都不是什么新算法,但是两者的结合效果还是令人惊叹,可以试试这个线性回归模拟器来熟悉下线性回归。
感知机
感知机最早由康奈尔航空实验室的心理学家弗兰克·罗森布拉特(Frank Rosenblatt)提出,罗森布拉特除了研究大脑学习能力,还爱好天文学,他能白天解剖蝙蝠研究学习迁移能力,夜晚还跑到自家屋后山顶建起天文台研究外太空生命。1958年,罗森布拉特模拟神经元发明感知机,以一篇《New Navy Device Learns By Doing》登上纽约时报头条。
罗森布拉特这台机器很快吸引了大众视线,给这台机器看50组图片(每组由一张标识向左和一张标识向右的图片组成),在没有预先设定编程命令的情况下,机器可以识别出图片的标识方向。
每一次的训练过程都是以左边的输入神经元开始,给每个输入神经元都赋上随机权重,然后计算所有加权输入的总和,如果总和是负数,则标记预测结果为0,否则标记预测结果为1。
如果预测是正确的,不需要修改权重;如果预测是错误的,用学习率(learning_rate)乘以误差来对应地调整权重。
下面我们来看看感知机如何解决传统的或逻辑(OR)。
Python实现感知机:
等人们对感知机的兴奋劲头过后,马文·明斯基(Marvin Minsky)和西摩·帕普特(Seymour Papert) 打破了人们对这一思想的崇拜。当时明斯基和帕普特都在MIT的AI实验室工作,他们写了一本书证明感知机只能解决线性问题,指出了感知机无法解决异或问题(XOR)的缺陷。很遗憾,罗森布拉特在两年后的一场船难中遇难离世。
在明斯基和帕普特提出这一点的一年后,一位芬兰的硕士学生找到了解决非线性问题的多层感知机算法。当时因为对感知机的批判思想占主流,AI领域的投资已经干枯几十年了,这就是著名的第一次AI寒冬。
明斯基和帕普特批判感知机无法解决异或问题(XOR,要求1&1返回0):
对于左图的OR逻辑,我们可以通过一条线分开0和1的情形,但是对于右边的XOR逻辑,无法用一条线来划分。
人工神经网络
到了1986年,鲁梅尔哈特(David Everett Rumelhart)、杰弗里·辛顿(Geoffrey Hinton)等人提出反向传播算法,证明了神经网络是可以解决复杂的非线性问题的。当这种理论提出来时,计算机相比之前已经快了1000倍。让我们看看鲁梅尔哈特等人如何介绍这篇具有重大里程碑意义的论文:
我们为神经元网络提出了一种新的学习过程——反向传播。 反向传播不断地调整网络中的连接权重,最小化实际输出与期望输出之间的误差。 由于权重调整,我们加入了隐藏神经元,这些神经元既不属于输入层,也不属于输出层,他们提取了任务的重要特征,并对输出进行了正则化。反向传播这种创造有效特征的能力,将其与之前的算法(如感知器收敛过程)区别开来。
Nature 323,533-536(1986年10月9日)
为了理解这篇论文的核心,我们实现了DeepMind大神Andrew Trask的代码,这并不是随机选择的代码,这段代码被Andrew Karpathy斯坦福的深度学习课程、Siraj Raval在Udacity的课程中采用。更为重要的是,这段代码体现的思想解决了XOR问题,融化了AI的第一个冬季。
在我们继续深入之前,读者可以试试这个模拟器,花上一两个小时来熟悉核心概念,然后再读Trask的博客,接下来多熟悉代码。注意在X_XOR数据中增加的参数是偏置神经元(bias neurons),类似于线性函数中的常量。
这里结合的反向传播,矩阵乘法和梯度下降可能会绕晕你,读者可以通过可视化过程来理解。先注重去看背后的逻辑,不要想着一下子就能完全参透全部。
另外,读者可以看看Andrew Karpathy的反向传播那一课,玩转一下可视化过程,读读迈克尔·尼尔森(Michael Nielsen)的《神经网络与深度学习》书上这一章。
深度神经网络
深度神经网络指的是除了输入层和输出层,中间还存在多层网络的神经网络模型,这一概念首先由加利福尼亚大学计算机系认知系统实验室的Rina Dechter提出,可参考其论文《Learning While Searching in Constraint-SaTIsfacTIon-Problems》,但深度神经网络的概念在2012年才得到主流的关注,不久后IBM IBM Watson在美国智力游戏危险边缘(eopardy)取得胜利,谷歌推出了猫脸识别。
深层神经网络的核心结构仍保持不变,但现在开始被应用在不同的问题上, 正规化也有很大的提升。一组最初应用于简化噪音数据的数学函数,现在被用于神经网络,提高神经网络的泛化能力。
深度学习的创新很大一部分要归功于计算能力的飞速提升,这一点改进了研究者的创新周期,那些原本需要一个八十年代中期的超级计算机计算一年的任务,今天用GPU只需要半秒钟就可以完成。
计算方面的成本降低以及深度学习越来越丰富的库资源,使得大众也可以走进这一行。我们来看一个普通的深层学习堆栈的例子,从底层开始:
GPU 》 Nvidia Tesla K80。通常用于图像处理,对比CPU,他们在深度学习任务的速度快了50-200倍。
CUDA 》 GPU的底层编程语言。
CuDNN 》 Nvidia优化CUDA的库
Tensorflow 》 Google的深度学习框架
TFlearn 》 Tensorflow的前端框架
我们来看一个数字分类的例子(MNIST数据集),这是一个入门级的例子,深度学习界的“hello world”。
在TFlearn中实现:
有很多经典的文章解释了MNIST问题,参考Tensorflow文档、JusTIn Francis的文章以及Sentdex发布的视频。
如果读者还想对TFlearn有进一步了解,可参考作者Emil Wallner之前的博客文章。
总结
如同上图的TFlearn示例,深度学习的主要思想仍然很像多年前罗森布拉特提出的感知机,但已经不再使用二进制赫维赛德阶跃函数(Heaviside step function),今天的神经网络大多使用Relu激活函数。在卷积神经网络的最后一层,损失设置为多分类的对数损失函数categorical_crossentropy,这是对勒让德最小二乘法的一大改良,使用逻辑回归来解决多类别问题。另外优化算法Adam则起源于德比的梯度下降思想。此外, Tikhonov的正则化思想被广泛地应用于Dropout层和L1 / L2层的正则化函数。