↖  理解计算:从根号2到AlphaGo -12:第5季 导数的前世今生-3..


-loading- -loading- -loading-

2019-10-11 , 206 , 0 , 144

听音频 🔊 . 看视频 🎦

现在我们打算忘掉所有关于代价函数的具体形式、神经⽹络的连接等等这些让人望而却步的东西。想象只要最⼩化⼀个给定的多元函数。假设我们要最⼩化某些函数,C(v)。

它可以是任意的多元实值函数,这里⽤v代替了w和b以强调它可能是任意的函数,为了可视化, 想象c是⼀个只有两个变量v1和 v2的函数,如下图12所示:

图12 两个变量的简单函数的极值[4].webp

图12 两个变量的简单函数的极值[4]

 

我们想要的是寻找某个(些)v1和v2的值,使得代价函数C取得全局最⼩值,此时的v1和v2就是让代价最小的参数。

当然,为了可视化,上图的函数依然简单,通常函数C可能是⼀个复杂的多元函数。现在想象一下这个函数不能通过找到导数为零的点来求极值了,原因是函数太复杂,导数的具体形式不容易得到。在这种情况下,为了找到全局最小值,⾸先把我们的函数想象成⼀个⼭⾕。

想象有⼀个⼩球从⼭⾕的斜坡滚落下来。⽇常经验告诉这个球因为重力的原因最终会滚到⾕底。这个日常的经验十分重要,它是神经网络发展历程中所有跌宕起伏的关键。

在深度学习领域,这个想法甚至与物理学中树上落下苹果催生了牛顿万有引力定律一样重要,它催生了所谓的梯度下降算法。


首先让球体随机选择⼀个起始位置,然后松手,观察球体滚落到⾕底的运动,球体的运动轨迹就是函数本身,前面已经提到,导数实际上正是反映函数形状的,因此我们可以通过计算C的导数(或者⼆阶导数)来简单模拟——这些导数会告诉我们⼭⾕中局部“形状”的⼀切,由此我们只需要计算导数就可以模拟球将怎样滚动,而不用实际的球。

所以,我们完全忽略球体的⽜顿运动定理,也不考虑摩擦⼒、重⼒等影响,从而避免陷进物理学⾥凌乱的细节。

为了更精确地描述这个问题,让我们思考⼀下,当我们在 v1 和 v2 ⽅向分别将球体移动⼀个很⼩的量,即 ∆v1 和 ∆v2 时,球体将会发⽣什么情况。微积分告诉我们 C 将会有如下变化:

fig12.PNG


然后我们⽤它再次更新规则来计算下⼀次移动。如果我们反复持续这样做,我们将持续减⼩C 直到获得⼀个全局的最⼩值(乐观的讲,在很多情况下,这是不可能的)。这就是梯度下降算法的整个过程。梯度下降算法避免了直接去寻找导数零点的极值,而是采用了一种迭代的方法,这个方法本质上类似于求解根号2一样,找到一种比较好的更新策略,即通过选择梯度相反反向向计算的目标迈进。


我们在第2季已经指出了学习的根本目标是为了处理未来(未知数据)的情况,因此这里需要再次表明学习与优化的不同,在大多数机器学习问题中,我们的根本目标是关注定义于测试集(模拟的未知数据)上的性能度量 P . 

然而,我们能做的只是间接地优化 P。我们希望通过降低在训练集上定义的一个代价(损失)函数 C 来提高 P。

尽管看起来我们做的核心工作变成了单纯的优化最小化 C本身。但是我们的目标则是提高学习在测试集上的性能P,而不单是在训练集上的C。


3 导数的计算

是时候介绍求导的方法了。 求导的方法大概分为四种方法,分别是手动求导,数值微分,符号微分和自动微分。


3.1手动求导

手动求解出导数的公式,然后利用计算机编程实现,这种方法的适用面太窄,一是能够手动求解出导数公式的大都是一些特殊类型的函数,关于这一点也需要极高的智慧(伟大的欧拉则表现的异常出色),而且一旦函数稍有改变,整个导数也就全变了, 还需要重新编程,有点类似于程序设计中所说的“硬编码”,在现在的模块化时代,已经不合时宜。


3.2数值微分

数值微分是从导数的定义出发进行求导的一种直观的想法。

eq21.webp


这个方法主要是从运算出发,因此首先要求求解的目标函数本身具有解析的表达式,这样这个问题就可以看做是一个纯数学符号问题,利用上面的加法和乘法原则进行导数的分解计算。

-loading- -loading--loading-


这个方法也广泛应用在数学软件如Matlab、Maple及Mathematica中。符号微分将一个表达式首先表示成一个表达式树,如我们要求符号表达式f(x) = 2x + x2,表达式树如下所示:

UfqiLong

fig13.PNG


基于表达式树和求导规则,我们可以得到最终的导数。然而,它的问题在于很多目标函数本身很难给出具体的形式或者解析表达式,更危险的是还会导致出现所谓的表达式膨胀问题(expression swell),也就是说机器不会自动的进行表达式的简化合并,当表达式太复杂的时候,计算导数变得更加耗时,下面的表1则清楚的说明了这个问题。


表1 符合微分的表达式膨胀问题[6]

表1 符合微分的表达式膨胀问题[6].webp

可以看到,Ln随着逐渐变得复杂,(d/dn)Ln的多项式个数则急剧增加。这就导致计算效率的降低。


3.4自动微分

自动微分是在1964年由Wengert提出[7],那个时候真正的电子计算机才不过发明十几年而已。自动微分的名字实际上有些让人困惑,几乎不能透露出这种算法的基本思想。

自动微分法实际上一种形式上采用符号微分的数值微分方法,因此可以看作是符合微分和数字微分的组合。数值微分从导数定义开始求数值近似解;符号微分强调直接对代数进行求解,最后才代入数值;自动微分则只对基本函数或常数运用符号微分法则,并通过链式法则将构成运算的导数结合起来,得到整体构成的导数。

所以它可以灵活结合编程语言的循环结构,条件结构等,并且由于它的计算实际是一种图计算,可以对其做很多优化。

实际上,另一种图计算模型-概率图模型在深度学习兴起之前也曾经是机器学习社区一个主流的方法。

由于概率图模型和图计算模型本质上的图属性,因此我们也谈到过在图论的基本思想或者一些操作可能将会对人工智能新的发展产生更大的影响。

图14 一个简单的计算图模型[6].PNG


其中v<sub>𝑖−𝑛</sub> = x𝑖是输入变量,v<sub>𝑖</sub>是中间变量y<sub>𝑚−𝑖</sub> = v<sub>𝑙−𝑖</sub>是输出变量。现在我们计算图中每一个节点的值以及它对应的导数的值。计算的过程主要分为两种形式: 前向微分和逆向微分。


3.4.1前向微分

前向微分是从输入变量开始,从左至右,根据计算图的方向,利用导数计算规则,计算导数的方法,如下表2所示

表2 前向微分的计算流程[6]

表2 前向微分的计算流程[6].webp


左图是三行分别对应于输入变量、中间变量以及输出变量节点的值,其中输入x1=2 ,x2=5. 右边的是图中每一个节点关于输入变量x1的偏导数的值,注意右图自上而下的箭头表明了,前向微分的计算顺序从输入层开始。

例如,v̇=dv/dx1,这里明显使用了牛顿流数的记号。注意到每一步的求导都利用到上一步的求导结果,这样不至于重复计算,从而避免了“表达式膨胀”问题。这个模型尽管在求解关于一个变量的偏导数上避免了重复计算,但是不可避免的是,在计算关于x2的偏导数时,几乎还要进行一遍类似上面的计算。


这里需要指明的是在神经网络学习时,x1和x2实际上就是神经网络的参数w,我们的目标是就是求解输入f对于w的导数,多元情况下则希望求解出由偏导数构成的梯度。

不幸的是,根据目前网络的复杂程度和发展趋势来看,w参数个数基本上都在成百上千万,甚至以亿记。

这种前向自动微分就太低效了,因此这种方法从一开始就几乎没有产生足够的影响力。这里我们需要强调一下, 计算图与神经网络结构图的区别。以最简单的单层神经网络,感知机为例,展示一下这种表示方法的不同之处。

图15 神经元的网络结构图(左)以及计算图.webp


图15 神经元的网络结构图(左)以及计算图


他们的相同点是都是有向图,在神经元(网络)结构图的表示中,图中的圆表示一个神经元,一般由“求和”和“激活”两部分构成,以反映出神经元”全或无”法则,输入x和输出y 有时也表示成一个圆,但最核心的网络参数则一般写在有向图中的弧边上,它隐含的表示了有向弧中箭尾表示的神经元的输出需要与权值参数w相乘才能作为下一个神经元的输入。

-loading- -loading--loading-


UfqiLong

而在计算图中,我们关心的并不是网络结构,而是如何方便的刻画参数w对输出y的影响(导数的作用)。在计算图中每一个圆均表示一个变量(或常量),计算图中的有向箭头则表示参与某种运算规则。在神经网络结构图中获得更新w参数的方法并不明显。

可遗憾的是,很多介绍参数优化问题时依然从神经网络的结构图上进行介绍,这导致更新w的方法,从形式上看非常的复杂,不容易让人理解。就跟他们的名字一样,结构图反映了网络的结构,计算图则反映了如何通过计算导数来寻找网络参数w的一个基本思路,我相信从计算图的角度进行参数的更新将是未来介绍神经网络计算过程的一个基本方法,下面的例子将会说明这一点。


3.4.2逆向微分

逆向微分实际上是一种通用形式的反向传播(BP)方法,逆向微分和反向传播方法分别在数值计算领域和神经网络领域里被不同的人多次发现,关于他们各自的历史可以分别参考文献[8]和文献[9]。有很大程度上是因为在当时学术的交流滞后性很强,同时交叉学科的发展也只是在近期才有了长足进步。 逆向微分是从最终结果开始求导,利用最终输出对每一个节点进行求导。其具体计算过程如下表3所示:


表3 逆向微分的计算流程[6]

表3 逆向微分的计算流程[6].webp


上表左边和之前的前向微分是一样的,右边则是逆向求导的计算过程,注意箭头表示的计算过程,也就是一开始先计算输出y对于节点v5的导数,用,这个计算结果需要保留下来,以便用于后续计算,而不必重复计算。由链式法则我们可以计算输出对于每个节点的导数。

图16 简单的计算图模型[10].PNG

图16 简单的计算图模型[10]

其中,c,d表示中间结果。 假设输入变量a=2,b=1时,图中各结点的偏导计算结果如下,在弧的中间灰色的方框中表示: 

图18 从底部(“叶子”节点)开始的前向微分[10].PNG

图19 从顶部(根)开始的逆向微分[10].webp

图19 从顶部(根)开始的逆向微分[10]

现在,所有常见的深度学习框架,Theano, Torch以及TensorFlow,都集成反向传播的求导的功能,同时,PyTorch等一些框架则试图将更加通用的自动求导(AD)作为其核心功能。

导数的在两百多年的历史中,再一次活跃在如今最前沿的计算平台上,在全世界最先进的计算设备上,开始展现出它的无穷魅力。


4 写在最后

本文回顾了导数的历史,简单介绍了导数在优化问题中的作用,以及如何求导三个方面的问题,我想我们已经对神经网络中的核心问题有了更加清晰的了解,目前来看基于导数的优化在深度学习中处于核心地位.

本季只是简单的介绍了其基本思想,针对基本问题的改进完善几乎成了深度学习研究最多的方面,特别是反向传播或者说逆向微分,简直成了深度学习利器,有意思的是这个利器被封装以后,我们几乎不再关心求导这个核心问题了。


一些学者试图摆脱BP方法的限制,除了该方法本身有其弱点之外,另一方面可能是因为,整个深度学习所依赖的基于梯度下降的方法从原理上看起来是那么简单(实际工作起来很痛苦),而人工智能则看起来那么的复杂,这样的矛盾让追求极致完美的科学家实在是受不了.

他们必须寻求突破。那么我们到底需要一种简单算法还是需要复杂算法才能实现与人一样的智能呢?我也不知道,我估计也没人知道。本文以《神经网络与深度学习》[4]这本书的最后一句来结束: “好吧,这些研究发展中的⼀部分研究需要有数百个诺⻉尔奖作为垫脚⽯。[4]”


牛顿的“6accdae13eff7i319n404qrr4s8t12vx”到底是什么意思呢?答案已在文中,不知道大家能不能找到这个彩蛋!


美妙时光美景风光——山川河流大西北新疆风景-4

+导数 +微分 +函数 +表达式 +变量

本页Url

↖回首页 +当前续 +尾续 +修订 +评论✍️


👍10 仁智互见 👎1
  • 还没有评论. → +评论
  • -loading- -loading- -loading-


    🔗 连载目录

    🤖 智能推荐

    + 柳谷书 柳谷书
    AddToFav   
    新闻 经典 官宣