数学四大算法(理解计算从根号2到AlphaGo)
SIGAI 特邀作者:twinlj77
作者简介:大学教师
研究方向:机器学习、信息安全
1 导数的历史
“ 6accdae13eff7i319n404qrr4s8t12vx ”
这段外表看起来有点像区块链地址(16进制地址)的乱码,第一次让接近神的牛顿爵士不得不以一种密码学的方式声明他对另一项重要研究的首发权,而这一次,他的对手则是当时欧洲大陆数学的代表人物,戈特弗里德·威廉·莱布尼茨,如图1所示。在科学史上,没有哪一个争论能够和牛顿与莱布尼茨的争论相比较,因为他们争夺的是人类社会几乎所有领域中无可取代的角色,反应变化这一最普遍现象极限的理论:微积分。 对教师而言,在大学的微积分教学很多都流于机械,不能体现出这门学科是一种震撼心灵的智力奋斗的结晶。对很多同学而言,回忆起高等数学中微积分的内容,简直是一段不堪回首的往事。
图1 牛顿(左)与莱布尼茨
本文无意愿也无能力详细阐述微积分发展的历程,这是一条经过近两个世纪几代数学家的努力,形成的漫长而曲折的思想潮流。现在将牛顿和莱布尼茨视为这门学科的发明人主要是因为他们几乎同时(先后)独立发明了一种新型的运算方法,这些方法尽管与现在课本上的有一些不同,但本质上和现代微积分是一样的,他们的方法对后来导数和积分概念的发展起到了奠基性的作用。他们的发明得益于他们的前辈,笛卡尔,费马,沃利斯以及牛顿的老师巴罗,如图2所示。在他们之后,为微积分做出巨大贡献的还有其他几位数学家,最杰出的代表则是神奇的伯努利兄弟(雅各布 伯努利和约翰伯努利),还有举世无双和蔼可亲的欧拉,以及为微积分严密化做出巨大贡献的柯西,黎曼,勒贝格等。本文先简要介绍他们的工作,然后引出导数在解决某些问题上的优势,最后引出自动求导这一计算机时代的需求。需要再次说明的是,笔者无法保证数学上的绝对严谨性,希望以一种直观直白的表达,而这显然与现代分析学的精确术语不太相符。
图2 微积分发明前的一些数学下,从左至右分别是笛卡尔,费马,沃利斯以及巴罗
在17世纪,计算曲线之下面积是一个在数学界十分热门的话题,就跟现在深度学习在人工智能领域的热门程度差不多。牛顿在1669年在他的那本经典的《分析学》书中, 讨论了他很早就发明的“通过无穷级数来计算曲线下”面积的方法。在这本书中,他利用自己发明的二项式定理(一种将两个数之和的整数次幂展开成类似项之和的恒等式的方法),开始对级数随意的,自由的使用,同时结合他更早时候就发明并开始使用的一种被称为流数的神秘方法来解决很多计算问题。最著名的就是书中求解面积的法则1[1].这奠定了微积分的基础。
法则1 : 简单曲线的面积:如果y = axm/n是曲线AD的函数,其中a是常数,m和n是正整数,那么区域ABD的面积为:
见图3(a).
图3 牛顿《分析学》中关于简单曲线面积的证明[1]
伟大的牛顿在证明过程中充分施展了他的超凡智慧,用到了他自己发明的二项式定理和流数,开创了微积分历史的先河。传统的求面积的方法都是作为用无限小的面积和的极限来定义的定积分的等价物而来。牛顿则反其道而行,首先假定面积为
,
然后通过考虑在x点处的面积的瞬时变化率。为了得到变化率,他考察了当x增加一个无穷小量o, z(x o)则表示就是面积Aβδ,如图3(b)所示。接下来,通过对[z(x)]和[z(x o)]和进行二项式展开做差,并除以o,特别是在需要的时候让无穷小o等于零或不等于零,并且通过一些变量的代换,最终他的到了一个神奇的结果:y = axm/n。按照现在的观点看来,牛顿把积分结果微分了。接着,在没有进一步证明的情况下, 他得出结论:与此相反,如果y = axm/n,那么
,
证明完毕。
这样的证明实在是不清楚,连他自己也说:“这是简略地说明,而不是正确的论证”。这个论证最重要的一点在于他透露出牛顿的一种奇特思路,纵坐标y可以看作是面积的增加速度,而横坐标x则是时间,纵坐标和很小的一段x区间相乘,就得到一个很小部分的面积,曲线下的面积就是这些所有面积的和。那些早于牛顿的科学家通过所有这样的小单元之和来求总面积,而牛顿则通过一点上的变化率来求出整个面积。在这个论证中,最为关键的是决定面积变化率,也就是我们今天所说的导数的概念,而积分则是用它定义的。然而,我们一会儿将看到将积分定义在导数之上,实际上花费了更长的时间。不管怎样,随着牛顿这个论证的给出,微积分终于出现在数学的历史中。一句话,牛顿用面积的瞬时变化率来求面积的方法创立了微积分。这真是一种简洁的难以理解的形式。在1736年,牛顿终于出版了1671年写的《流数法与无穷级数》,并正式的将变化率称为流数,用字母上方一点表示,变化的量则为流量。x是流量,ẋ是流数。然而在当时,无法给出无穷小量在流数定义中的合理性,牛顿强调流数从不是单独的而总是在比中来考虑的,流数被牛顿认为是一个逐渐消失量的比,连牛顿自己都觉得他的说法让人怀疑。
作为哲学家的莱布尼茨兴趣广泛,他曾凭借发明的一个机械式计算器而加入英国皇家学会。他曾花费时间,大量阅读令人敬仰的数学家的作品,直到他“阅读文献就如同别人阅读浪漫小说一样轻松”[1]。对自己成功的坚定信念使他确定只要努力就可以称为令人敬仰的数学家,事实证明,确实如此。为了解决曲线AB下的面积,莱布尼茨采用了一种通用且更容易理解的方式,将这个面积想象无穷多个小矩形构成,这些小矩形面积的和就是曲线下的面积。他把这些小矩形的宽度看作dx,长度为y,在伯努利兄弟的建议下,用∫ 表示这个求和过程,积分号∫实际上一个伸长了的“求和(Summa)”的首字母。莱布尼茨为了得到∫ 的值,采用了一种几何和代数相结合的方式,首先,通过一些相似三角形的应用,他先获得了如下图4(a)所示的无限多个小三角形的面积的和,也就是
图4 莱布尼茨简单曲线面积的证明[1]
其中,
, 曲线AB下的面积=楔形面积 三角形ObB面积-三角形OaA面积, 如图4(b) 所示即
这样求解AB下面积∫ 的问题被转化为一个新的积分项和两个常数项的和了,这就是莱布尼茨的积分变换定理,这个定理的优势在于对z的积分很可能比原来直对y的积分更容易,数学上的变换一般都是如此。从理论上而言,最为关键的一点是z的值实际上与切线的斜率关系密切(注意z中dy/dx这一项)。积分与导数的关系已经若隐若现了。然而,莱布尼茨的问题在于所有一切的基础,微分dx或者dy的定义不明确,莱布尼茨认为dx是一个无限小的不可分的长度,这实在是很矛盾的。尽管最早的时候,莱布尼茨甚至跟我们一样, 有时会吃不准d(xy)跟dxdy以及d(x/y跟dy/dx是否一样,他依然给出了d(xy)=xdy ydx,以及的d(x/y)=(ydx-xdy)/y2的正确结果,而且在他晚年,他意识到值得重视的并不是一个一个的微分,而是他们的比值。
牛顿和莱布尼茨被称为微积分的奠基者是因为他们清楚的阐述了微积分的基本问题,“已知量的关系,要算出他们的流数,以及反过来”,尽管那时候对他们来说基于极限的严格意义上的导数还没有出现,。不管是牛顿流数方法中的无穷小量o,以及莱布尼茨微分中的微分dx都有说不清道不明的逻辑基础,他们都介乎存在与不存在之间的灰色地带,牛顿和莱布尼茨也经常徘徊在很多不清楚的概念之上。但是不管怎样,他们已经开创了庞大的分析学帝国的广阔领域。尽管在当时英国的数学界都公认牛顿首先发明了微积分,但是牛顿的性格以及他的流数符号的局限性却使英国真正丧失了数学中心的位置,从此以后,数学的中心在莱布尼茨的带领下,开始在欧洲大陆落地生根。接下来,为了建立更加严格的基础,欧洲大陆的数学家花费了两百多年的时间。
作为莱布尼茨的狂热支持者与学生,伯努利兄弟(哥哥雅各布和弟弟约翰)可以说是数学史上最著名的兄弟。约翰比雅各布小13岁,在哥哥门下学习了两年,雅各布从此称弟弟为“我的学生”,尽管学生的才能已经与他不相上下。约翰很是不服气,经常自豪的谈起如何在一个晚上解决了困扰雅各布一年的问题,但是,当他在1696年提出最速降线问题的时候,花了两周时间解决这个问题的他将题目亲自寄给牛顿,牛顿经过一天造币厂的辛苦劳动后,一个晚上就解决了该问题并匿名寄给了约翰。当接到匿名信的那一刻,约翰惊呼:” Ah! I recognize the lion by his paw.” 约翰为法国贵族洛必达侯爵提供了世界上第一本微积分教科书的大部分素材,书中出现了由约翰发明的洛必达法则,约翰曾抱怨洛必达用金钱换取他人的智慧,但是拿人手短,洛必达法则就这样成了一个不是发明人命名的法则,没办法,毕竟人家付了钱。
图5 雅各布伯努利与约翰伯努利兄弟,以及微积分的传播者洛必达侯爵
尽管关于微分比的概念不清楚,历史出版著作最多的数学家, 约翰·伯努利的学生欧拉在他的《分析学原理》中给出了很多微分之比,他已经意识到微分学的强大之处在于它同研究两个无穷小量的比值相关,尽管这个时候连他也无法明确什么是无穷小。最为著名的微分之比就是它通过级数证明时y=sinx时,dy/dx=cos。当欧拉去世时,正是莱布尼茨发表第一篇微积分论文99周年,在这近100年的时间里,分析学取得了巨大进展。在这一个世纪里面,数学家们对曲线的几何性质依赖越来越少,在级数的基础上,开始对函数的代数运算依赖越来越多,而且只限于特定函数的积分或者级数,对于一般意义上的连续函数或是可微函数并不重视[2]。在这一百年,由于概念不清楚的无穷小量的存在,微积分的基础依然令人怀疑和难以理解。有一些数学家尝试建立更加完善的基础,达朗贝尔提出了建立在“极限”概念上的微积分。他把dy/dx看作是有限项的商的极限。他将这个商表示成z/u,那么dy/dx就是假定z和u是实数,并且不断减少,比值z/u越来越接近的量。但是由于缺少对极限的明确定义,困境依然存在。欧拉的学生,拉格朗日试图建立排除无穷小量,逐渐消失的量,极限等不明确的概念的微积分,他通过把f(x i)表示成i的无穷级数的形式:
其中p,q,r..是从函数x得到的且与i无关的新函数。这个级数就是泰勒级数,不过他认为这个级数再先,导数作为一种这个级数存在的结果。这样构造级数来寻找导数的方法的问题是无法保证这个级数能够收敛到原始的函数。
图 6 达朗贝尔和拉格朗日
在欧拉去世后不久,一位在现代大学本科高等数学课本中举足轻重的人物,柯西诞生了。这位处于古典微积分和现代分析学过度时期最著名的数学家,完善了工科高等数学现代教科书中绝大部分核心概念:极限,连续性以及导数。在柯西之前,数学家们凭借着直觉和聪明才智取得了重大成就,在他之后,微积分的逻辑标准逐渐严格,从字面上看,分析学变得更加枯燥和不容易理解,同时也更加完备,无论是初学者还是数学家,几乎丧失了质疑的勇气。柯西认为必须把全部微积分建立在极限的思想基础上,并且给出了相当经典的关于极限概念的定义:“当属于一个变量(数列或函数)的相继的值无限地趋近于(接近)某个固定的值时,如果最终同固定值之差可以随意的小,那么这个固定值就称为所有这些值(数列或函数)的极限。[2]” 柯西的伟大之处在于在极限的定义上,避免提及如何达到极限或超过极限,而仅仅是通过引入一个随意小的值接近并保持接近它。类似的他给出关于“无穷小量”的定义,当一个变量的连续数值无限减小(小于任何给定的值)时,这个变量就是无穷小量,实际上就是量的极限为0。接着柯西开始考虑连续性。从函数y=f(x)开始,他令i为无穷小量,然后考察用x i替代x时,函数的值,这个值的从y变为y △y,也就是△y=f(x i)-f(x),对于无穷小的的i,如果插值△y也是无穷小,柯西就称f(x)为x的连续函数。这里无穷小的使用看起来字面上与牛顿的无穷小量和莱布尼茨的dx没有区别, 但是此时的无穷小已经建立在极限为零的概念之上了,这是微积分严格化历史上最为重要的工作之一。即连续性实际上是指
,这等价于今天的
。接着柯西考虑了微商,定义了导函数:
, 其中i为无穷小量, 这里柯西采用了拉格朗日的标记,将导数记为′或者′(). 柯西在分析学中的意义来源于对极限所做的定义,同时他提倡微积分中大量的定理必须用这个定义去证明。需要说明的是,在柯西之前,尽管积分已经广泛使用,但是更多是把积分看作是微分的一个逆过程,在概念上来讲一直从属于微分,由微分导出。柯西则认为积分是独立存在的,并且应该有自身的定义。从连续函数出发,他定义函数 Φ(x)=
,并且证明了 Φ(x)=f(x),柯西把这个结果重新写成
, 这正是微积分基本定理的最初形式,微分和积分的可逆性质从来没有这么清晰的展现在人们面前。
图7 柯西,魏尔施特拉斯,黎曼以及勒贝格
19世纪60年代以后,魏尔斯特拉斯创造了ε-δ语言,对微积分中出现的各种类型的极限重新表达,就是我们所有人都学习过的高等数学课本中极限的定义(请对照查看同济版高等数学函数极限的定义):
一句话,ε-δ是一种精确描述极限(无限接近某个值)的数学语言,这种数学语言的思想由柯西提出,最终由魏尔斯特拉斯完成定义。从此以后,对于没有思想准备的数学门外汉而言,数学建立了一道形式化的门槛。
1840年,当中国陷于鸦片战争的境地时,在世界范围内的数学领域中,没有人不知道柯西。1859年,大清帝国著名的数学家李善兰与汉学家英国人伟烈亚力(Wylie Alexander,1815~1887)合作翻译了美国数学家E·罗密士(Elias Loomis,1811-1889)的《解析几何与微积分》出版,取名《代微积拾级》,这是是西方微积分著作的第一部中文译本。不久之后,这本书传到日本,第一次将欧洲数学带入日本数学界。今天我们熟悉的高等数学中很多的名词,“微分”,“积分”,“函数”,“级数”,“极大”,“极小”,“方程式”,“全微分”,“曲率“,”曲线”以及“横轴纵轴”等大都来自于这本创世的译作。中国文化的博大精深从这些译文中你也应该深有体会,现在我们再也找不到比这些更完美的译文了。尽管柯西的研究对现代分析学产生了重要影响,然而他的积分仅限于连续函数,对数学精确性的权威解释还要,再半个多世纪的等待,因为那个时候,关于实数,这个数学家经常使用但是却对其根本性质依然不清楚的概念继续得到完善,随着与集合论的结合,分析学也彻底的改变了其自身的面貌。时间进入到二十世纪,我已无法对分析学完备的过程做更多的解释(主要是泛函分析没学好),20世纪上半叶,分析学经过黎曼,魏尔斯特拉斯的不断严格化,随着实数的完备性逐渐清晰, 最终由勒贝格把微积分严格化的革命带入到实分析这一现代分析学领域。简单的说,就是他定义了称之为勒贝格积分的东西使得积分能够在更广阔的领域开展工作,而不仅仅限于连续函数,他的积分更具有普遍性。
图 8 李善兰与伟烈亚力
除了微积分,莱布尼茨兴趣广泛,也是自动计算最早期的思想来源,他提出了通用编码语言,用素数表示主要概念,从而形成一个数字和思想的完美映射,同时他把二进制编码看作是通用编码的关键,并从中国易经的卦象中得到二进制表示的灵感,还给出了10进制和2进制之间转换的方法[3]。人类智能的一个关键特征是“无限使用有限方法”的能力,其中一小部分元素可以以无限的方式有效的组合在一起,人类的语言和文字就是典型代表,当然也包括莱布尼茨提出的极简到0-1的二进制。时间是如此的巧合,在二十世纪上半叶,人类历史上最伟大的理论成果微积分经过两百多年得历程完成了它严格化的历程。而就在不久之后,同样,在莱布尼茨伟大思想的指引下,在普林斯顿高等研究院的冯诺依曼与他的同事撰写了《电子计算机逻辑设计初探》(Preliminary discussion of the the logical design of an electronic computing instrument),最终实现了莱布尼茨在数字计算和通用语言方面的梦想[3]。尽管当时电子计算机那时刚刚来到这个世界。从理论上而言,导数已经变得不在让人不安。计算导数的任务则像其他繁琐的事务一样,开始由人工转向借助于计算机了。我们逐渐清楚的了解了导数的历程。现在是时候看看导数的威力,并寻求一些更好的求导方法了。
2 导数的作用
在牛顿和莱布尼茨还要更早一些,大约在1629年,法国数学家费马研究了作曲线的切线和求函数极值的方法;从一开始,导数就与极值问题联系密切。由于当时连函数的概念都不清楚,因此更多的从几何角度谈论函数,也就是曲线。曲线在某一点的导数,则形象化的被看作是在这一点上切线的斜率。导数的变化实际上反映了函数(曲线)的形态上的变化。而且我们一般在实际使用过程中,更加关注那些位于特定形状端点的那些值。现在假设有一个函数y = f(x),当f′(x) = 0,当的时候,表明在这一点x的斜率为0,f′(x)的点称为临界点或驻点。临界点除了局部极小点(local minimum)、局部极大点(local maxmum)外,还有鞍点,鞍点(saddle points)既不是最小点也不是最大点, 如下图9所示:
图9 斜率为零的三种临界点[5]
在这种简单情况下(函数有具体形式且能够得到导数), 通过求解导数为零的点,就能相对比较容易的得到函数的极值点。如果我们能够得到这些临界点,那么函数的基本形态也就在我们的掌控之中了。使f(x)取得全局最小值的点是全局最小点。只有一个全局最小点(global minimum)或存在多个全局最小点的函数是有可能的。一般的情况则是存在不是全局最优的局部极小点,这种情况更加常见,如图10所示。
图10 存在多个局部极小点的情况[5]
然而,不幸的是,直接利用该方法计算导数去寻找函数的极值点在一些更复杂的情况下几乎没什么用处。特别是函数变量过多的话那就是噩梦。为了更清楚的看清这个问题,可以看看下面的多层感知机(MLP,实际上MLP的激活函数不是感知机的阶跃函数而已经变成了S形的Sigmod函数,但是由于历史原因,依然称之为多层感知机):
图11 多层感知机[4]
在前一季中,我们已经知道明斯基已经认识到多层感知机能够解决XOR问题,但根本原因是无法找到一个可行的寻找多层感知机参数的方法。实际上多层感知机(甚至所有的神经网络)本身是一个复合函数,表示为f(.),最重要的一点是,根据端到端的学习的基本思想,我们希望⽹络(函数的另一种说法)的输出f(x)能够满足所有数据本身的响应,这个时候我们就认为网络学习好了,可以用来进行处理数据了。就跟我们在第一季介绍感知机时说的那样寻找直线(f(x))来分类一样,错分样本会产生代价,此时的目标不过是稍微复杂一些罢了,为了量化我们如何实现这个⽬标,我们这里也定义⼀个简单的代价函数:
这⾥ w 表⽰所有的⽹络中权重的集合,b是所有的偏置,n是训练输⼊数据的个数,f(x)是表⽰当输⼊为 x 时网络的输出,y表示x对应的实际类别,求和则是在总的训练输⼊x上进⾏的。代价函数没有什么特殊和神秘,本质上是为f来拟合x和y之间的对应关系寻找一个量化的标准罢了,代价函数的基本原则就是希望输出与本身的标记或者期望的响应接近。因此,我们将会看到,大部分代价函数样子很类似。当然,输出f(x)取决于x, w和b,但是为了保持符号的简洁性,我没有明确地指出这种依赖关系。因此如果我们能找到合适的权重和偏置,使得C(w; b)≈0,则表明f(x)比较好,我们就有较高的信心让f来处理未知的数据x’。相反,当C(w; b)很⼤时那意味着对于⼤量地输⼊, y 与输出 f(x) 相差很⼤,这种映射关系肯定不是我们想要的。因此我们的⽬的,是最⼩化代价函数 C(w; b),具体来说就是寻找复合函数法f(x)中w,b的值,使得对于已知的训练样本x和其标记y产生的代价C(w; b)最小。
现在我们打算忘掉所有关于代价函数的具体形式、神经⽹络的连接等等这些让人望而却步的东西。想象只要最⼩化⼀个给定的多元函数。假设我们要最⼩化某些函数,C(v)。它可以是任意的多元实值函数,这里⽤v代替了w和b以强调它可能是任意的函数,为了可视化, 想象c是⼀个只有两个变量v1和 v2的函数,如下图12所示:
图12 两个变量的简单函数的极值[4]
我们想要的是寻找某个(些)v1和v2的值,使得代价函数C取得全局最⼩值,此时的v1和v2就是让代价最小的参数。当然,为了可视化,上图的函数依然简单,通常函数C可能是⼀个复杂的多元函数。现在想象一下这个函数不能通过找到导数为零的点来求极值了,原因是函数太复杂,导数的具体形式不容易得到。在这种情况下,为了找到全局最小值,⾸先把我们的函数想象成⼀个⼭⾕。想象有⼀个⼩球从⼭⾕的斜坡滚落下来。⽇常经验告诉这个球因为重力的原因最终会滚到⾕底。这个日常的经验十分重要,它是神经网络发展历程中所有跌宕起伏的关键。在深度学习领域,这个想法甚至与物理学中树上落下苹果催生了牛顿万有引力定律一样重要,它催生了所谓的梯度下降算法。首先让球体随机选择⼀个起始位置,然后松手,观察球体滚落到⾕底的运动,球体的运动轨迹就是函数本身,前面已经提到,导数实际上正是反映函数形状的,因此我们可以通过计算C的导数(或者⼆阶导数)来简单模拟——这些导数会告诉我们⼭⾕中局部“形状”的⼀切,由此我们只需要计算导数就可以模拟球将怎样滚动,而不用实际的球。所以,我们完全忽略球体的⽜顿运动定理,也不考虑摩擦⼒、重⼒等影响,从而避免陷进物理学⾥凌乱的细节。为了更精确地描述这个问题,让我们思考⼀下,当我们在 v1 和 v2 ⽅向分别将球体移动⼀个很⼩的量,即 ∆v1 和 ∆v2 时,球体将会发⽣什么情况。微积分告诉我们 C 将会有如下变化:
只要是∆C一个负值,意味着C将往小的地方移动,因此我们的目标变成要寻找⼀种选择 ∆v1 和 ∆v2 的⽅法使得∆C为负;即,我们选择它们是为了让球体滚落。为了更清晰的看到这一点,需要定义 ∆v为v变化的向量,∆v ≡ (∆v1, ∆v2), T 是转置符号,我们也定义 C 的梯度为偏导数的向量,
, ⽤∇C来表⽰梯度向量,即:
因此,∆C的表达式可以被重写为:
这个⽅程真正厉害之处是它让我们看到了如何选取∆v才能让∆C为负数。假设我们选取:
这⾥的η是个很⼩的正数(称为学习速率),我们在第4季时有专门介绍。这个式子告诉我们
。由于
,这保证了
,即,如果我们按照这个⽅程的规则去改变v,那么C会⼀直减⼩,不会增加。因此我们把⽅程⽤于定义球体在梯度下降算法下的“运动定律”。也就是说,我们⽤⽅程计算∆v,来移动球体的位置 v:
然后我们⽤它再次更新规则来计算下⼀次移动。如果我们反复持续这样做,我们将持续减⼩C 直到获得⼀个全局的最⼩值(乐观的讲,在很多情况下,这是不可能的)。这就是梯度下降算法的整个过程。梯度下降算法避免了直接去寻找导数零点的极值,而是采用了一种迭代的方法,这个方法本质上类似于求解根号2一样,找到一种比较好的更新策略,即通过选择梯度相反反向向计算的目标迈进。
我们在第2季已经指出了学习的根本目标是为了处理未来(未知数据)的情况,因此这里需要再次表明学习与优化的不同,在大多数机器学习问题中,我们的根本目标是关注定义于测试集(模拟的未知数据)上的性能度量 P . 然而,我们能做的只是间接地优化 P。我们希望通过降低在训练集上定义的一个代价(损失)函数 C 来提高 P。尽管看起来我们做的核心工作变成了单纯的优化最小化 C本身。但是我们的目标则是提高学习在测试集上的性能P,而不单是在训练集上的C。
3 导数的计算
是时候介绍求导的方法了。 求导的方法大概分为四种方法,分别是手动求导,数值微分,符号微分和自动微分。
3.1手动求导
手动求解出导数的公式,然后利用计算机编程实现,这种方法的适用面太窄,一是能够手动求解出导数公式的大都是一些特殊类型的函数,关于这一点也需要极高的智慧(伟大的欧拉则表现的异常出色),而且一旦函数稍有改变,整个导数也就全变了, 还需要重新编程,有点类似于程序设计中所说的“硬编码”,在现在的模块化时代,已经不合时宜。
3.2数值微分
数值微分是从导数的定义出发进行求导的一种直观的想法。
根据导数的定义,我们可以设置一个很小的h,来近似计算这个导数,这个方法简单粗暴,所以很容易编程实现,但是问题也显而易见。由于h无法真正为零,因此会导致产生所谓的截断误差(Truncation error)或近似误差(error of approximation),另外由于机器本身表示数字的不准确性则会产生舍入误差(Round-off error)。然而更大的问题是这个的复杂度,对一维函数来说相对容易,但是随着维数n的增加,用于计算所有维上的导数的开销将增加,达到O(n)。这对现在几千万维的函数来说简直是一种灾难。因此更多的时候,这个算法并不用来直接进行计算导数,而是用来检验其他算法计算出的导数的正确性。用导数的定义来验证导数计算的准确性,应该没有比这更好方法了吧!
3.3符号微分
符号微分则依赖于莱布尼茨给出的关于求导的加法和乘法原则:
这个方法主要是从运算出发,因此首先要求求解的目标函数本身具有解析的表达式,这样这个问题就可以看做是一个纯数学符号问题,利用上面的加法和乘法原则进行导数的分解计算。这个方法也广泛应用在数学软件如Matlab、Maple及Mathematica中。符号微分将一个表达式首先表示成一个表达式树,如我们要求符号表达式f(x) = 2x x2,表达式树如下所示:
图13 表达式的树形表示
利用求导的加法和乘法原则,可以求出:
基于表达式树和求导规则,我们可以得到最终的导数。然而,它的问题在于很多目标函数本身很难给出具体的形式或者解析表达式,更危险的是还会导致出现所谓的表达式膨胀问题(expression swell),也就是说机器不会自动的进行表达式的简化合并,当表达式太复杂的时候,计算导数变得更加耗时,下面的表1则清楚的说明了这个问题。
表1 符合微分的表达式膨胀问题[6]
可以看到,
随着逐渐变得复杂,
的多项式个数则急剧增加。这就导致计算效率的降低。
3.4自动微分
自动微分是在1964年由Wengert提出[7],那个时候真正的电子计算机才不过发明十几年而已。自动微分的名字实际上有些让人困惑,几乎不能透露出这种算法的基本思想。自动微分法实际上一种形式上采用符号微分的数值微分方法,因此可以看作是符合微分和数字微分的组合。数值微分从导数定义开始求数值近似解;符号微分强调直接对代数进行求解,最后才代入数值;自动微分则只对基本函数或常数运用符号微分法则,并通过链式法则将构成运算的导数结合起来,得到整体构成的导数。所以它可以灵活结合编程语言的循环结构,条件结构等,并且由于它的计算实际是一种图计算,可以对其做很多优化。实际上,另一种图计算模型-概率图模型在深度学习兴起之前也曾经是机器学习社区一个主流的方法。由于概率图模型和图计算模型本质上的图属性,因此我们也谈到过在图论的基本思想或者一些操作可能将会对人工智能新的发展产生更大的影响。
以如下的公式为例:
它对应的计算图如下所示:
图14 一个简单的计算图模型[6]
其中v− = x是输入变量,v是中间变量y− = v−是输出变量。现在我们计算图中每一个节点的值以及它对应的导数的值。计算的过程主要分为两种形式: 前向微分和逆向微分。
3.4.1前向微分
前向微分是从输入变量开始,从左至右,根据计算图的方向,利用导数计算规则,计算导数的方法,如下表2所示
表2 前向微分的计算流程[6]
左图是三行分别对应于输入变量、中间变量以及输出变量节点的值,其中输入x1=2 ,x2=5. 右边的是图中每一个节点关于输入变量x1的偏导数的值,注意右图自上而下的箭头表明了,前向微分的计算顺序从输入层开始。例如,
v̇=dv/dx1,这里明显使用了牛顿流数的记号。注意到每一步的求导都利用到上一步的求导结果,这样不至于重复计算,从而避免了“表达式膨胀”问题。这个模型尽管在求解关于一个变量的偏导数上避免了重复计算,但是不可避免的是,在计算关于x2的偏导数时,几乎还要进行一遍类似上面的计算。这里需要指明的是在神经网络学习时,x1和x2实际上就是神经网络的参数w,我们的目标是就是求解输入f对于w的导数,多元情况下则希望求解出由偏导数构成的梯度。不幸的是,根据目前网络的复杂程度和发展趋势来看,w参数个数基本上都在成百上千万,甚至以亿记。这种前向自动微分就太低效了,因此这种方法从一开始就几乎没有产生足够的影响力。这里我们需要强调一下, 计算图与神经网络结构图的区别。以最简单的单层神经网络,感知机为例,展示一下这种表示方法的不同之处。
图15 神经元的网络结构图(左)以及计算图
他们的相同点是都是有向图,在神经元(网络)结构图的表示中,图中的圆表示一个神经元,一般由“求和”和“激活”两部分构成,以反映出神经元”全或无”法则,输入x和输出y 有时也表示成一个圆,但最核心的网络参数则一般写在有向图中的弧边上,它隐含的表示了有向弧中箭尾表示的神经元的输出需要与权值参数w相乘才能作为下一个神经元的输入。而在计算图中,我们关心的并不是网络结构,而是如何方便的刻画参数w对输出y的影响(导数的作用)。在计算图中每一个圆均表示一个变量(或常量),计算图中的有向箭头则表示参与某种运算规则。在神经网络结构图中获得更新w参数的方法并不明显。可遗憾的是,很多介绍参数优化问题时依然从神经网络的结构图上进行介绍,这导致更新w的方法,从形式上看非常的复杂,不容易让人理解。就跟他们的名字一样,结构图反映了网络的结构,计算图则反映了如何通过计算导数来寻找网络参数w的一个基本思路,我相信从计算图的角度进行参数的更新将是未来介绍神经网络计算过程的一个基本方法,下面的例子将会说明这一点。
3.4.2逆向微分
逆向微分实际上是一种通用形式的反向传播(BP)方法,逆向微分和反向传播方法分别在数值计算领域和神经网络领域里被不同的人多次发现,关于他们各自的历史可以分别参考文献[8]和文献[9]。有很大程度上是因为在当时学术的交流滞后性很强,同时交叉学科的发展也只是在近期才有了长足进步。 逆向微分是从最终结果开始求导,利用最终输出对每一个节点进行求导。其具体计算过程如下表3所示:
表3 逆向微分的计算流程[6]
上表左边和之前的前向微分是一样的,右边则是逆向求导的计算过程,注意箭头表示的计算过程,也就是一开始先计算输出y对于节点v5的导数,用
,这个计算结果需要保留下来,以便用于后续计算,而不必重复计算。由链式法则我们可以计算输出对于每个节点的导数。
比如对于节点v3:
单纯的从后往前的这个简单的逆向操作,为何有这么大的威力呢?最后我们看一个简单的计算图模型来进一步了解这一点,假设计算表达式为e = (a b) ∗ (b 1),它的计算图模型为:
图16 简单的计算图模型[10]
其中,c,d表示中间结果。 假设输入变量a=2,b=1时,图中各结点的偏导计算结果如下,在弧的中间灰色的方框中表示:
图17 相邻节点的偏导数的计算[10]
接下来, 利用前向微分,我们计算e关于b的偏导,此时把这个图看做类似于树的结构,从底部开始,我们需要计算所有变量关于b的偏导,最终在根节点得到
图18 从底部(“叶子”节点)开始的前向微分[10]
而利用反向微分算法,我们直接从树的根节点(严格来说不是树,而是图的输出变量e)开始,首先计算
,然后利用链式法则,根据各节点的偏导数计算得到中间变量以及最后叶子节点(输入节点)的偏导数,注意在树的底部,我们看到,反向求导的方法几乎同时得到了
,当叶子节点(输入变量)的个数是几百万甚至上千万的神经网络的参数的时候,这种逆向求导的方法则成百万倍的提高了导数(偏导)计算的效率,这就是为什么逆向微分(反向传播)能够取得成功的根本原因。
图19 从顶部(根)开始的逆向微分[10]
现在,所有常见的深度学习框架,Theano, Torch以及TensorFlow,都集成反向传播的求导的功能,同时,PyTorch等一些框架则试图将更加通用的自动求导(AD)作为其核心功能。导数的在两百多年的历史中,再一次活跃在如今最前沿的计算平台上,在全世界最先进的计算设备上,开始展现出它的无穷魅力。
4 写在最后
本文回顾了导数的历史,简单介绍了导数在优化问题中的作用,以及如何求导三个方面的问题,我想我们已经对神经网络中的核心问题有了更加清晰的了解,目前来看基于导数的优化在深度学习中处于核心地位,本季只是简单的介绍了其基本思想,针对基本问题的改进完善几乎成了深度学习研究最多的方面,特别是反向传播或者说逆向微分,简直成了深度学习利器,有意思的是这个利器被封装以后,我们几乎不再关心求导这个核心问题了。一些学者试图摆脱BP方法的限制,除了该方法本身有其弱点之外,另一方面可能是因为,整个深度学习所依赖的基于梯度下降的方法从原理上看起来是那么简单(实际工作起来很痛苦),而人工智能则看起来那么的复杂,这样的矛盾让追求极致完美的科学家实在是受不了,他们必须寻求突破。那么我们到底需要一种简单算法还是需要复杂算法才能实现与人一样的智能呢?我也不知道,我估计也没人知道。本文以《神经网络与深度学习》[4]这本书的最后一句来结束: “好吧,这些研究发展中的⼀部分研究需要有数百个诺⻉尔奖作为垫脚⽯。[4]”
牛顿的“6accdae13eff7i319n404qrr4s8t12vx”到底是什么意思呢?答案已在文中,不知道大家能不能找到这个彩蛋!
参考文献
[1] 微积分的历程:从牛顿到勒贝格 [The Calculus Gallery:Masterpieces from Newton to Lebesgue] ,[美] 邓纳姆 著,李伯民,汪军,张怀勇 译,人民邮电出版社,2010-08-01
[2] 微积分概念史:对导数与积分的历史性的评论,[美]卡尔·B·波耶 ,上海师范大学数学系翻译组 ,上海人民出版社, 1977
[3] 图灵的大教堂: 数字宇宙开启智能时代[美] 乔治·戴森 , 盛杨灿 译,浙江人民出版社,2015-5
[4]Michael A. Nielsen, “Neural Networks and Deep Learning(神经⽹络与深度学习)”,Determination Press, 2015
[5] Ian Goodfellow and Yoshua Bengio and Aaron Courville Deep Learning, MIT Press, 2016
[6] Atilim Gunes Baydin, Barak A. Pearlmutter, Alexey Andreyevich Radul, Jeffrey Mark Siskind, Automatic differentiation in machine learning: a survey,https://arxiv.org/abs/1502.05767
[7]Robert E. Wengert. A simple automatic derivative evaluation program. Communications of the ACM, 7:463–4, 1964.
[8]Andreas Griewank. Who invented the reverse mode of differentiation? Documenta Mathematica, Extra Volume ISMP:389–400, 2012.
[9]J¨urgen Schmidhuber. Deep learning in neural networks: An overview. Neural Networks, 61: 85–117, 2015.
[10] Christopher Olah, Calculus on Computational Graphs: Backpropagation http://colah.github.io/posts/2015-08-Backprop/
,免责声明:本文仅代表文章作者的个人观点,与本站无关。其原创性、真实性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容文字的真实性、完整性和原创性本站不作任何保证或承诺,请读者仅作参考,并自行核实相关内容。文章投诉邮箱:anhduc.ph@yahoo.com