第二季 · 第 56 章 沿着山坡寻找最低点标记本章已读大字阅读打印本章回到上次阅读位置《算法的故事》第二季 · 第六篇:会学习的算法——1847年,柯西如何发现一种让错误不断减小的计算方法第56章配图1847年10月18日,法国巴黎。法国科学院的一次会议上,一位数学家提出了一个看起来并不复杂的问题。如果我们需要同时求解很多个方程,却没有办法直接消去所有未知数,应该怎么办?比如,未知数有六个。方程可能更多。这些方程之间相互关联。某些方程还包含难以直接求解的非线性关系。传统方法通常试图通过代数变换,将多个未知数一步步消去。但消元过程有时会变得异常复杂。甚至无法方便地完成。这位数学家提出,是否可以换一种思考方向?我们不必一开始就要求所有方程同时精确成立。而是先找到一个办法,衡量当前答案究竟偏离了目标多少。然后不断修正未知数。让这个偏离程度越来越小。直到满足方程。或者至少得到一个足够好的近似结果。这位数学家是:奥古斯丁-路易·柯西(Augustin-Louis Cauchy)。他在1847年发表的论文题目是:Méthode générale pour la résolution des systèmes d'équations simultanées《求解联立方程组的一般方法》。论文刊登于《Comptes Rendus de l'Académie des Sciences》第25卷,第536—538页。根据当时的会议记录与后来的文献整理,这项报告于1847年10月18日宣读。 [gtfp.cs.rhul.ac.uk][滑铁卢大学计算机科学系]论文只有短短几页。但其中包含一个后来影响深远的想法。如果我们已经知道函数在当前位置朝什么方向增加得最快,那么,朝相反方向移动,是否就能够让函数下降?柯西用偏导数描述了这项计算。他考虑给未知数施加一组与函数偏导数方向相反的小变化。这样,函数值在足够小的步长下就会降低。对于今天的读者而言,这个想法有一个非常熟悉的名称。Gradient Descent梯度下降。第56章配图将近一百八十年后,世界上的研究者依然在使用与它密切相关的优化方法。在统计学中,调整回归参数。在机器学习中,降低预测误差。在计算机视觉中,训练图像识别模型。在语言模型中,利用大量训练样本更新神经网络权重。这些任务远比1847年的联立方程组复杂。现代优化器也远远不止柯西当年提出的基本方法。但它们之间保留着一条重要的数学联系。把难以直接求解的问题变成一个可以衡量的目标,然后利用局部变化信息,反复调整参数。现在,我们要把时间重新拨回1847年。看看这个想法到底是怎样出现的。第一幕:1847年,柯西真正想解决的不是机器学习,而是联立方程组第56章配图1847年的柯西,已经是欧洲数学界极有影响力的人物。他的研究涉及:微积分的严格基础。微分方程。复分析。力学。天体运动。以及各种数学计算方法。但是,任何真正处理过复杂方程的人都知道:一个数学问题即使可以写成明确的公式,也不意味着我们能够方便地求出答案。传统的办法:消元假设有两个方程:{x+y=52x−y=1\begin{cases} x+y=5\\ 2x-y=1 \end{cases}{x+y=52x−y=1这很容易。两式相加:3x=63x=63x=6所以:x=2,y=3x=2,\qquad y=3x=2,y=3但如果我们遇到:{f1(x,y,z)=0f2(x,y,z)=0f3(x,y,z)=0\begin{cases} f_1(x,y,z)=0\\ f_2(x,y,z)=0\\ f_3(x,y,z)=0 \end{cases}⎩⎨⎧f1(x,y,z)=0f2(x,y,z)=0f3(x,y,z)=0而这些函数包含复杂的乘积、幂次或者其他非线性关系,代数消元就未必简单。柯西在1847年论文开头,明确讨论了传统消元法的两类困难:有时无法方便地进行消元。即使完成消元,剩下的方程也可能非常复杂。于是,他提出一种迭代改进的思路。[滑铁卢大学计算机科学系]把多个方程变成一个非负函数假设原问题是:f1(x,y)=0f_1(x,y)=0f1(x,y)=0f2(x,y)=0f_2(x,y)=0f2(x,y)=0我们构造:E(x,y)=f1(x,y)2+f2(x,y)2\boxed{ E(x,y)=f_1(x,y)^2+f_2(x,y)^2 }E(x,y)=f1(x,y)2+f2(x,y)2由于平方永远非负:E(x,y)≥0E(x,y)\ge0E(x,y)≥0而如果:E(x,y)=0E(x,y)=0E(x,y)=0那么必然有:f1(x,y)=0,f2(x,y)=0f_1(x,y)=0,\qquad f_2(x,y)=0f1(x,y)=0,f2(x,y)=0所以,只要能找到使E为0的点,我们就解决了原来的联立方程组。这就是把:求解方程。转变为:最小化一个函数。图56-1:从联立方程到目标函数原问题f1(x,y)=0,f2(x,y)=0f_1(x,y)=0,\qquad f_2(x,y)=0f1(x,y)=0,f2(x,y)=0↓构造非负的误差函数E(x,y)=f1(x,y)2+f2(x,y)2E(x,y)=f_1(x,y)^2+f_2(x,y)^2E(x,y)=f1(x,y)2+f2(x,y)2↓转化后的任务minx,yE(x,y)\min_{x,y}E(x,y)minx,yE(x,y)但这项转化存在一项必须保留的区别。如果:minE=0\min E=0minE=0就说明找到了满足全部方程的解。可如果:minE>0\min E>0minE>0那么,只能说找到了某种误差较小的近似结果。它并不意味着原来的全部方程已经被精确满足。而且,即使某种迭代算法停在一个局部极小点,也不能立即断定它找到了全局最优值。这些区别对于现代机器学习同样重要。柯西论文中的真实数学步骤原论文首先考虑一个非负函数:u=f(x,y,z,…)u=f(x,y,z,\ldots)u=f(x,y,z,…)希望找到使:u=0u=0u=0的变量。他用:X=∂u∂x,Y=∂u∂y,Z=∂u∂zX=\frac{\partial u}{\partial x}, \qquad Y=\frac{\partial u}{\partial y}, \qquad Z=\frac{\partial u}{\partial z}X=∂x∂u,Y=∂y∂u,Z=∂z∂u表示各方向的偏导数。然后考虑给变量施加:Δx=−θX\Delta x=-\theta XΔx=−θXΔy=−θY\Delta y=-\theta YΔy=−θYΔz=−θZ\Delta z=-\theta ZΔz=−θZ其中:θ>0\theta>0θ>0并且足够小。根据一阶近似:f(x+Δx,y+Δy,z+Δz)≈u+XΔx+YΔy+ZΔzf(x+\Delta x,y+\Delta y,z+\Delta z) \approx u+X\Delta x+Y\Delta y+Z\Delta zf(x+Δx,y+Δy,z+Δz)≈u+XΔx+YΔy+ZΔz代入后:fnew≈u−θ(X2+Y2+Z2)\boxed{ f_{\mathrm{new}} \approx u-\theta(X^2+Y^2+Z^2) }fnew≈u−θ(X2+Y2+Z2)因为:X2+Y2+Z2≥0X^2+Y^2+Z^2\ge0X2+Y2+Z2≥0所以,只要梯度不为零,而且步长足够小,函数值在局部就会下降。这项推导与1847年原论文第537页的关键公式一致。[滑铁卢大学计算机科学系]原论文还有一个常被忽略的细节柯西并不是只说:“随便选择一个很小的步长就好。”他还讨论了:沿下降方向选择一个能使函数进一步减小的步长。并写出了沿该方向对步长求导、寻找一维最小值的思想。这与后来最速下降法中的:Line Search(线搜索)具有直接的数学联系。但我们不应把1847年这篇短论文,描述成已经包含了现代优化理论里全部关于全局收敛、Lipschitz梯度、随机梯度和神经网络训练的成果。那些都是后来的数学家和工程师逐步发展出来的。为什么天体计算也出现在原论文里?柯西当时还关注天体轨道确定问题。在论文结尾,他提到可以利用这类方法处理确定天体轨道时得到的有限方程,并结合观测的经度、纬度等数据进一步改进计算结果。这是一项真实的历史背景,不是后人为梯度下降补写的故事。[滑铁卢大学计算机科学系]于是,一件非常有趣的事发生了。一项今天广泛应用于人工智能训练的数学思想,最初的重要应用背景之一,却是复杂方程和天体运动的数值计算。第二幕:山坡上的人,为什么只看脚下也能知道往哪里走?第56章配图现在,让我们暂时把偏导数放在一边。想象你站在一座山上。四周被雾遮住。你看不到山谷的全貌。不知道全局最低点位于哪个方向。但你可以观察脚下地面的倾斜情况。如果目的是尽快沿局部最陡的方向下降,你可以选择:当前坡度下降最快的方向。走一小步。重新观察坡度。再走一步。不断重复。这就是梯度下降最直观的形象。但这里隐藏着两项限制。第一:你只能看到当前局部的坡度。第二:你还需要决定每一步走多远。即使每一步都朝向局部下降方向,也不意味着一定能够到达整座山的最低处。因为山地可能拥有:局部山谷。鞍点。平坦区域。以及复杂的弯曲地形。数学中的梯度是什么?假设一个函数:f(x,y)f(x,y)f(x,y)表示二维位置对应的高度。那么梯度就是:∇f(x,y)=[∂f∂x∂f∂y]\boxed{ \nabla f(x,y)= \begin{bmatrix} \frac{\partial f}{\partial x}\\[4pt] \frac{\partial f}{\partial y} \end{bmatrix} }∇f(x,y)=[∂x∂f∂y∂f]它是一个向量。其中:∂f∂x\frac{\partial f}{\partial x}∂x∂f表示沿x方向变化时,函数如何变化。而:∂f∂y\frac{\partial f}{\partial y}∂y∂f表示沿y方向变化时,函数如何变化。为什么梯度指向最陡上升方向?假设我们选择一个长度为1的方向向量:u\mathbf uu沿该方向的方向导数为:Duf=∇f⋅uD_{\mathbf u}f=\nabla f\cdot\mathbf uDuf=∇f⋅u根据柯西–施瓦茨不等式:∇f⋅u≤∥∇f∥∥u∥\nabla f\cdot\mathbf u \le \|\nabla f\|\|\mathbf u\|∇f⋅u≤∥∇f∥∥u∥由于:∥u∥=1\|\mathbf u\|=1∥u∥=1得到:Duf≤∥∇f∥\boxed{ D_{\mathbf u}f\le\|\nabla f\| }Duf≤∥∇f∥等号在:u=∇f∥∇f∥\mathbf u= \frac{\nabla f}{\|\nabla f\|}u=∥∇f∥∇f时成立。因此,当梯度非零时:∇f\nabla f∇f指向局部增长最快的单位方向。而:−∇f-\nabla f−∇f指向局部下降最快的单位方向。注意:这里说的是在欧几里得距离度量下,给定相同的极小位移长度,哪一个方向的瞬时下降最快。如果改变距离度量,或对参数采用不同尺度,所谓“最陡”的方向也可能改变。这一点对于后来的预条件优化方法非常重要。梯度下降的标准更新式假设当前参数向量是:xt\mathbf x_txt我们选择:η>0\eta>0η>0作为步长。那么:xt+1=xt−η∇f(xt)\boxed{ \mathbf x_{t+1} = \mathbf x_t-\eta\nabla f(\mathbf x_t) }xt+1=xt−η∇f(xt)在机器学习中:η\etaη通常被称为:Learning Rate(学习率)。从数学结构看,这就是柯西早期下降方向思想的现代常见表达。但“学习率”这一术语属于后来机器学习语境。1847年的论文并不是在讨论现代神经网络权重更新。一个必须立刻澄清的事实梯度下降选择的是局部下降方向。它并不保证任意正学习率都会让函数下降。如果步长太大,可能跨过最低点。甚至走到比原来更高的地方。因此,问题并没有在找到负梯度以后彻底解决。我们还需要研究:每一步应该走多远?这就是下一幕的核心问题。第三幕:只有一个未知数时,学习率的秘密已经全部暴露出来第56章配图我们先不处理复杂神经网络。只研究一条抛物线。设:f(x)=(x−3)2\boxed{f(x)=(x-3)^2}f(x)=(x−3)2它的最低点显然位于:x∗=3x^*=3x∗=3最低函数值:f(3)=0f(3)=0f(3)=0现在假设计算机并不知道这个答案。它只知道:当前位置。函数值。以及当前位置的导数。我们从:x0=0x_0=0x0=0开始。第一步:计算导数f′(x)=2(x−3)f'(x)=2(x-3)f′(x)=2(x−3)在:x=0x=0x=0处:f′(0)=−6f'(0)=-6f′(0)=−6因为导数是负数,所以函数在这个位置向右下降。梯度下降更新:xt+1=xt−ηf′(xt)x_{t+1}=x_t-\eta f'(x_t)xt+1=xt−ηf′(xt)因此:x1=0−η(−6)=6ηx_1=0-\eta(-6)=6\etax1=0−η(−6)=6η注意:只要改变学习率,下一步的位置就会完全不同。情况一:学习率为0.1η=0.1\eta=0.1η=0.1那么:x1=0.6x_1=0.6x1=0.6继续迭代:x2=1.08x_2=1.08x2=1.08x3=1.464x_3=1.464x3=1.464函数值逐渐减小。迭代xxxf(x)f(x)f(x)00910.65.7621.083.686431.4642.3593每一步都朝着:x=3x=3x=3接近。情况二:学习率为0.5η=0.5\eta=0.5η=0.5那么:x1=0−0.5×(−6)=3x_1=0-0.5\times(-6)=3x1=0−0.5×(−6)=3只需要一步,就到达了最低点。是不是意味着学习率永远越大越好?当然不是。情况三:学习率为1η=1\eta=1η=1那么:x1=6x_1=6x1=6第二次更新:x2=0x_2=0x2=0第三次:x3=6x_3=6x3=6程序不断在:000和:666之间来回跳动。函数值始终是:999它没有真正逼近最低点。情况四:学习率为1.1η=1.1\eta=1.1η=1.1第一步:x1=6.6x_1=6.6x1=6.6第二步:x2=−1.32x_2=-1.32x2=−1.32下一步会走到更远的位置。这种震荡的幅度将越来越大。算法开始发散。为什么可以精确预测这些行为?因为:xt+1=xt−2η(xt−3)x_{t+1} = x_t-2\eta(x_t-3)xt+1=xt−2η(xt−3)整理:xt+1−3=(1−2η)(xt−3)x_{t+1}-3=(1-2\eta)(x_t-3)xt+1−3=(1−2η)(xt−3)令:et=xt−3e_t=x_t-3et=xt−3表示距离最优点的误差。得到:et+1=(1−2η)et\boxed{e_{t+1}=(1-2\eta)e_t}et+1=(1−2η)et因此:et=(1−2η)te0\boxed{ e_t=(1-2\eta)^t e_0 }et=(1−2η)te0要让误差趋近0,需要:∣1−2η∣<1|1-2\eta|<1∣1−2η∣<1解得:0<η<1\boxed{0<\eta<1}0<η<1这就是这条简单抛物线上,固定学习率梯度下降收敛的精确条件。图56-2:学习率决定的是哪一种运动学习率误差倍率 1−2η1-2\eta1−2η结果0.10.8同侧逐步收敛0.50一步到达最低点0.9−0.8交替跨越,但仍收敛1.0−1持续等幅震荡1.1−1.2震荡发散一个非常重要的发现这项例子中:梯度始终计算正确。下降方向也始终是:−∇f-\nabla f−∇f但算法仍然可能发散。所以,算法失败未必来自:梯度计算错误。它也可能来自:步长选择不合适。这正是为什么,梯度下降不能只记住:x←x−η∇f(x)x\leftarrow x-\eta\nabla f(x)x←x−η∇f(x)还必须理解:η\etaη与目标函数的曲率之间的关系。而在多维函数中,这项关系会变得更加复杂。第四幕:一条狭长山谷,为什么会让梯度下降左右摇摆?第56章配图现在,我们把问题从一个变量扩展到两个变量。考虑:f(x,y)=12(x2+8y2)\boxed{ f(x,y)=\frac12(x^2+8y^2) }f(x,y)=21(x2+8y2)它的最低点位于:(0,0)\boxed{(0,0)}(0,0)最低函数值:f(0,0)=0f(0,0)=0f(0,0)=0但它与圆形对称的抛物面不同。在y方向上,函数变化很快。在x方向上,函数变化相对较慢。因此,它的等高线不是圆形,而是狭长的椭圆。先求梯度∂f∂x=x\frac{\partial f}{\partial x}=x∂x∂f=x∂f∂y=8y\frac{\partial f}{\partial y}=8y∂y∂f=8y所以:∇f(x,y)=[x8y]\boxed{ \nabla f(x,y)= \begin{bmatrix} x\\ 8y \end{bmatrix} }∇f(x,y)=[x8y]对应更新:xt+1=xt−ηxtx_{t+1}=x_t-\eta x_txt+1=xt−ηxtyt+1=yt−8ηyty_{t+1}=y_t-8\eta y_tyt+1=yt−8ηyt整理:xt+1=(1−η)xt\boxed{ x_{t+1}=(1-\eta)x_t }xt+1=(1−η)xtyt+1=(1−8η)yt\boxed{ y_{t+1}=(1-8\eta)y_t }yt+1=(1−8η)yt现在出现了一项关键事实。同一个学习率,在两个方向上产生的收缩倍率完全不同。假设学习率为0.2那么:xt+1=0.8xtx_{t+1}=0.8x_txt+1=0.8xt而:yt+1=−0.6yty_{t+1}=-0.6y_tyt+1=−0.6yt意味着:x会缓慢向0移动。y则会在0的两侧交替跳跃,同时振幅逐渐减小。这就形成了梯度下降经常被画成的:Zigzag(之字形)路径。为什么陡峭方向会限制整体学习率?要让x方向收敛:∣1−η∣<1|1-\eta|<1∣1−η∣<1即:0<η<20<\eta<20<η<2但要让y方向收敛:∣1−8η∣<1|1-8\eta|<1∣1−8η∣<1即:0<η<0.250<\eta<0.250<η<0.25两个条件必须同时满足。所以:0<η<0.25\boxed{0<\eta<0.25}0<η<0.25如果:η=0.30\eta=0.30η=0.30虽然x方向仍然收敛,但y方向的误差倍率为:1−8×0.30=−1.41-8\times0.30=-1.41−8×0.30=−1.4它会反复跨越最低点,并且振幅越来越大。所以,整体函数值也会最终发散。Hessian矩阵告诉我们什么?对于二次函数:f(x)=12x⊤Hxf(\mathbf x)=\frac12\mathbf x^\top H\mathbf xf(x)=21x⊤Hx其中:H=[1008]H= \begin{bmatrix} 1&0\\ 0&8 \end{bmatrix}H=[1008]叫作:Hessian(海森矩阵)。它描述函数的二阶局部变化。在本例中,Hessian的特征值是:λmin=1\lambda_{\min}=1λmin=1λmax=8\lambda_{\max}=8λmax=8它们的比值:κ=λmaxλmin=8\boxed{\kappa=\frac{\lambda_{\max}}{\lambda_{\min}}=8}κ=λminλmax=8称为该正定二次型的:条件数(Condition Number)。条件数较大,意味着不同方向的曲率差异较明显。普通梯度下降可能不得不使用受陡峭方向限制的较小步长,从而导致平缓方向收敛缓慢。这正是后来优化理论中:预条件。动量。以及加速方法。持续研究的重要问题之一。这与机器学习有什么关系?现代神经网络的损失函数,远比这个二维二次函数复杂。但类似现象仍然可能出现。不同参数方向对损失的影响强度可能差别很大。某些方向很敏感。另一些方向变化缓慢。于是,同一个全局学习率,未必适合全部参数方向。但也不能因此简单地说,所有神经网络训练困难都来自“狭长山谷”。真实神经网络还可能涉及:非凸结构。随机梯度噪声。参数尺度。非线性激活。梯度消失或爆炸。以及其他复杂问题。我们的二维例子,只是将曲率与步长之间的关系清楚地展示出来。第五幕:1847年的线搜索,到了1966年为什么成为一条严格的数学规则?第56章配图现在,我们已经知道:固定学习率可能太小。也可能太大。如果每一步都使用同一个:η\etaη那么,即使函数的不同区域需要不同的调整幅度,算法也不会自动改变步长。有没有更聪明的办法?当然有。其中一条重要路线,是:Line Search(线搜索)。先决定方向,再决定走多远假设我们位于:xt\mathbf x_txt梯度是:gt=∇f(xt)\mathbf g_t=\nabla f(\mathbf x_t)gt=∇f(xt)我们已经知道负梯度是局部下降方向。所以,先设:dt=−gt\mathbf d_t=-\mathbf g_tdt=−gt然后,我们不立即决定固定步长。而是考虑沿该方向的一维函数:ϕ(η)=f(xt+ηdt)\boxed{ \phi(\eta)=f(\mathbf x_t+\eta\mathbf d_t) }ϕ(η)=f(xt+ηdt)现在,问题就变成:如何选择:η>0\eta>0η>0让:ϕ(η)\phi(\eta)ϕ(η)足够小?精确线搜索一种思路是:沿当前下降方向,找到使函数值最小的步长。即:ηt=argminη≥0ϕ(η)\boxed{ \eta_t=\arg\min_{\eta\ge0}\phi(\eta) }ηt=argη≥0minϕ(η)这叫作:Exact Line Search(精确线搜索)。柯西1847年的论文已经包含了沿选定下降方向进一步调整步长、寻找一维最小值的思想。但对于复杂函数,每一步都精确求出这个最优步长,也可能十分昂贵。所以,后来研究者还发展了更加实用的不精确线搜索方法。1966年:Larry Armijo的工作1966年,数学研究者:拉里·阿米霍(Larry Armijo)。发表:Minimization of Functions Having Lipschitz Continuous First Partial Derivatives《具有Lipschitz连续一阶偏导数的函数最小化》。发表于《Pacific Journal of Mathematics》第16卷第1期。论文证明了在适当条件下,梯度法与具有变步长机制的下降算法的收敛性质。[MSP]后来,一种非常常用的步长选择方法,就与Armijo的名字联系在一起。Armijo条件是什么意思?给定当前点:x\mathbf xx下降方向:d\mathbf dd以及常数:0<c<10<c<10<c<1我们希望找到:η>0\eta>0η>0使:f(x+ηd)≤f(x)+cη∇f(x)⊤d\boxed{ f(\mathbf x+\eta\mathbf d) \le f(\mathbf x)+ c\eta\nabla f(\mathbf x)^\top\mathbf d }f(x+ηd)≤f(x)+cη∇f(x)⊤d因为:∇f(x)⊤d<0\nabla f(\mathbf x)^\top\mathbf d<0∇f(x)⊤d<0所以右边比当前函数值低。这项条件要求:新位置获得足够的函数值下降。如果当前步长不满足条件,就将它缩小。例如:η←12η\eta\leftarrow\frac12\etaη←21η反复尝试。直到找到合适的步长。这叫作:Backtracking Line Search(回溯线搜索)。为什么不是只检查“新函数值比旧函数值低”?因为有时候,极小的步长也会带来非常微弱的下降。但这可能意味着更新非常低效。Armijo条件不仅要求函数下降,还要求下降幅度相对于:当前方向导数。和所选步长。达到一定标准。这使它比单纯的“下降一点点就接受”更加有结构。1966年的论文到底证明了什么?它没有证明:任何可微函数、任意初始点、任意参数设置,都一定能找到全局最低点。它是在明确的光滑性、下界及其他条件下,研究相关梯度下降方法的收敛性质。这种带着前提条件的数学证明,非常重要。因为它让数值优化逐渐从:“我们观察到这个方法似乎有效。”发展为:“在什么数学条件下,可以严格证明它有效?”这正是数值分析成为成熟学科的重要过程。第六幕:互动实验室——让小球从山坡出发,亲眼观察收敛、震荡与发散现在,我们把刚才的数学函数变成一张可以操作的等高线图。你可以改变:初始位置。学习率。山谷的陡峭程度。还可以在:固定学习率梯度下降。与:二次函数上的精确线搜索。之间切换。图中会显示每一次迭代的位置、运动路径和函数值。实验:二维损失函数地形图图56-3:二维梯度下降实验台目标函数为 f(x,y)=12(x2+cy2)f(x,y)=\frac12(x^2+cy^2)f(x,y)=21(x2+cy2)。椭圆是等高线,绿色星形标志是全局最低点。橙色折线表示算法实际移动的轨迹。选择山谷地形圆形山谷 c=1椭圆 c=4狭长 c=8步长选择方法固定学习率每步精确线搜索学习率 η0.20初始x-2.4初始y1.4最低点xy橙色:已计算路径图中显示的坐标范围约为−3.8至3.8。发散路径离开绘图区后不会全部显示,但下方数值仍反映算法的迭代结果。查看第几次迭代10 / 30当前函数值0.033491当前位置(-0.258, 0.008)本步η=0.2000当前地形的严格收敛步长条件是 0<η<0<\eta<0<η< 0.250。所选学习率满足当前正定二次函数的严格稳定条件。收敛示例持续震荡发散示例精确线搜索第一次实验:收敛选择:狭长山谷。固定学习率:η=0.10\eta=0.10η=0.10然后观察20次左右的迭代。你会发现,轨迹逐渐靠近:(0,0)(0,0)(0,0)函数值不断下降。第二次实验:震荡将学习率改成:η=0.25\eta=0.25η=0.25由于:1−8η=−11-8\eta=-11−8η=−1所以y坐标会在正负之间来回切换,绝对值却不减小。这意味着算法无法沿y方向真正收敛。即使x方向仍在逐步靠近0,整体函数也不会收敛到最低值。第三次实验:发散将:η=0.30\eta=0.30η=0.30你会看到,轨迹很快离开画面。因为:∣1−8η∣=1.4>1|1-8\eta|=1.4>1∣1−8η∣=1.4>1在y方向上,每次迭代的误差绝对值放大40%。程序并不是不知道最低点在中心。而是步长太大,使更新持续跨过谷底并越走越远。第四次实验:精确线搜索切换到:“每步精确线搜索”。对于:f(x)=12x⊤Hxf(\mathbf x)=\frac12\mathbf x^\top H\mathbf xf(x)=21x⊤Hx这种正定二次函数,设:gt=Hxt\mathbf g_t=H\mathbf x_tgt=Hxt那么,沿负梯度方向的最佳步长,可以直接计算为:ηt=gt⊤gtgt⊤Hgt\boxed{ \eta_t= \frac{\mathbf g_t^\top\mathbf g_t} {\mathbf g_t^\top H\mathbf g_t} }ηt=gt⊤Hgtgt⊤gt于是,每一步都不必手工指定固定学习率。但你也许会发现:即使每次都选择当前梯度方向上的最佳步长,狭长山谷里的下降路径仍然可能明显地左右摆动。原因在于:每一次只在当前梯度确定的一条直线上优化。而下一次梯度方向可能发生明显变化。因此,精确线搜索并不等于直接找到多维函数的全局最低点。对于某些条件数很大的二次型,它仍然可能收敛缓慢。这就是后来共轭梯度法、预条件方法和加速优化研究的数学背景之一。第七幕:1951年,如果每一次测量都带着噪声,梯度下降还能工作吗?第56章配图我们现在知道了怎样根据一个明确的数学函数计算梯度。但真实世界里的问题未必如此理想。例如,一位研究者正在通过实验寻找某项物理系统的最佳控制参数。他调整:xxx然后观察系统输出。但每次实验结果都会受到随机因素影响。温度可能变化。仪器存在测量误差。环境中有噪声。因此,即使使用完全相同的x,两次实验也可能得到不同结果。这意味着:研究者并不总能直接得到准确的目标函数。更不一定能计算出完全准确的梯度。那么:如果下降方向本身带着随机误差,能否仍然逐步逼近正确答案?1951年:Robbins与Monro1951年9月,统计学家:赫伯特·罗宾斯(Herbert Robbins)。以及:萨顿·门罗(Sutton Monro)。发表:A Stochastic Approximation Method《一种随机逼近方法》。刊登于《The Annals of Mathematical Statistics》第22卷第3期,第400—407页。[ML Anthology]他们研究的不是今天的大型神经网络。而是一项统计估计问题。假设某项实验在参数x下的期望输出为:M(x)M(x)M(x)但我们不知道这个函数的完整形式。我们希望找到:θ\thetaθ使:M(θ)=α\boxed{M(\theta)=\alpha}M(θ)=α其中:α\alphaα是目标水平。每次实验只能给出受随机因素影响的观测。能否通过反复实验与参数更新,逐渐逼近:θ\thetaθ?这正是随机逼近理论的重要研究方向。从精确梯度到带噪声的估计现代优化语言中,我们可以考虑:gt=∇f(xt)+εtg_t=\nabla f(x_t)+\varepsilon_tgt=∇f(xt)+εt其中:εt\varepsilon_tεt是梯度估计误差。如果在适当条件下:E[εt∣xt]=0E[\varepsilon_t\mid x_t]=0E[εt∣xt]=0那么:E[gt∣xt]=∇f(xt)E[g_t\mid x_t]=\nabla f(x_t)E[gt∣xt]=∇f(xt)也就是说:尽管某次估计可能偏离真实梯度,但它在条件期望意义下仍然指向正确的梯度。更新式变成:xt+1=xt−ηtgt\boxed{ x_{t+1}=x_t-\eta_tg_t }xt+1=xt−ηtgt这里的学习率:ηt\eta_tηt还可以随迭代次数变化。为什么随机学习率经常需要逐渐缩小?考虑一个直观问题。如果每次梯度都有随机误差,而我们永远使用相同的较大学习率,那么即使参数接近最优点,随机误差仍然可能把它反复推离。所以,在某些随机逼近收敛理论中,需要学习率序列满足:∑t=1∞ηt=∞\boxed{\sum_{t=1}^{\infty}\eta_t=\infty}t=1∑∞ηt=∞以及:∑t=1∞ηt2<∞\boxed{\sum_{t=1}^{\infty}\eta_t^2<\infty}t=1∑∞ηt2<∞第一项保证,学习率虽然逐渐减小,但累计调整能力不会过早耗尽。第二项则帮助控制随机噪声的长期累积影响。例如:ηt=at\eta_t=\frac{a}{t}ηt=ta其中:a>0a>0a>0就满足这两项求和性质。但必须说明:仅仅满足这两项学习率条件,并不能保证任意随机优化问题都会收敛。还需要对目标函数、噪声及其他条件做出适当假设。1952年:Kiefer与Wolfowitz随机逼近研究很快进一步发展。1952年,Jack Kiefer与Jacob Wolfowitz提出了用于随机函数优化的相关方法。他们研究如何在只能获得带噪声的函数观测时,借助有限差分估计变化趋势,并逐步寻找最优参数。这项研究与Robbins–Monro一起,构成现代随机优化的重要历史来源。但不能把1951年Robbins–Monro的原始论文,直接写成已经提出了今天神经网络训练中全部mini-batch SGD机制。这些方法之间具有重要的数学联系,却属于不断发展的不同研究阶段。为什么随机性有时不是缺点?因为如果我们拥有一百万条训练数据,每一步都必须完整读取全部数据,计算成本可能非常高。如果只随机使用一小部分数据,就有机会更快完成一次参数更新。单次更新虽然更加嘈杂,但可能使模型更频繁地获得反馈。这就成为后来机器学习中的:Stochastic Gradient Descent(随机梯度下降,SGD)。下一幕,我们将真正计算它与普通梯度下降有什么不同。第八幕:从一百万条样本中只抽几条,为什么也能训练模型?第56章配图假设我们希望训练一个最简单的预测模型。输入:xxx预测输出:y^=wx\hat y=wxy^=wx其中:www是我们希望通过数据学习的参数。现在有四条训练样本。输入x真实y12243648我们可以直接看出:w∗=2w^*=2w∗=2是完美拟合参数。但现在假设计算机需要从:w0=0w_0=0w0=0开始学习。定义损失函数对于单条样本,平方误差:ℓi(w)=12(wxi−yi)2\ell_i(w)=\frac12(wx_i-y_i)^2ℓi(w)=21(wxi−yi)2整个训练集的平均损失:L(w)=1N∑i=1N12(wxi−yi)2\boxed{ L(w)=\frac1N\sum_{i=1}^{N}\frac12(wx_i-y_i)^2 }L(w)=N1i=1∑N21(wxi−yi)2梯度:L′(w)=1N∑i=1N(wxi−yi)xi\boxed{ L'(w)=\frac1N\sum_{i=1}^{N}(wx_i-y_i)x_i }L′(w)=N1i=1∑N(wxi−yi)xi对于全部四条数据:L′(0)=14[(−2)×1+(−4)×2+(−6)×3+(−8)×4]L'(0) = \frac14[ (-2)\times1+ (-4)\times2+ (-6)\times3+ (-8)\times4 ]L′(0)=41[(−2)×1+(−4)×2+(−6)×3+(−8)×4]所以:L′(0)=−15\boxed{L'(0)=-15}L′(0)=−15如果学习率:η=0.05\eta=0.05η=0.05那么完整批量梯度下降给出:w1=0−0.05×(−15)w_1=0-0.05\times(-15)w1=0−0.05×(−15)得到:w1=0.75\boxed{w_1=0.75}w1=0.75如果只随机选择第一条样本呢?样本:(x,y)=(1,2)(x,y)=(1,2)(x,y)=(1,2)它对应的梯度:g1=(wx−y)xg_1=(wx-y)xg1=(wx−y)x在:w=0w=0w=0时:g1=−2g_1=-2g1=−2因此:w1=0.1w_1=0.1w1=0.1如果只随机选择第四条样本呢?样本:(x,y)=(4,8)(x,y)=(4,8)(x,y)=(4,8)梯度:g4=(−8)×4=−32g_4=(-8)\times4=-32g4=(−8)×4=−32所以:w1=1.6w_1=1.6w1=1.6同样的初始参数。同样的学习率。不同样本却可能产生很不同的更新幅度。但是,如果我们均匀随机选择一条样本:E[gi]=14∑i=14giE[g_i]=\frac14\sum_{i=1}^{4}g_iE[gi]=41∑i=14gi恰好等于完整批量梯度:E[gi]=L′(w)\boxed{E[g_i]=L'(w)}E[gi]=L′(w)这便是随机小批量训练的重要数学基础。Batch、SGD与Mini-batch图56-4:三种梯度估计方式Batch Gradient Descent(全批量梯度下降)12345678使用全部训练样本计算一次梯度。单样本SGD12345678随机选取一条样本,进行一次参数更新。Mini-batch SGD(小批量随机梯度下降)12345678使用一小组样本的平均梯度,进行一次参数更新。为什么现代深度学习常常使用Mini-batch?因为它在以下方面提供了有价值的权衡。一方面,不需要每更新一次参数,就计算整个数据集的全部样本。另一方面,相比单样本随机梯度,小批量平均通常可以降低梯度估计的方差。而且,现代GPU非常适合并行处理一个批次中的多条样本。因此,小批量训练往往能够较好地利用硬件。但也不能简单说:批量越大,训练就一定越好。因为批量大小还会影响:每次更新成本。梯度噪声。内存需求。参数更新次数。以及模型最终的泛化表现。所以,Batch Size(批大小)也是一项重要的训练超参数。SGD有时候为什么看起来会“走错方向”?因为单次随机梯度不等于真实完整梯度。某个小批次可能偶然给出偏离真实平均方向的估计。所以,SGD的损失函数轨迹未必每一步都单调下降。这与上一幕讨论的Armijo线搜索不同。Armijo线搜索通常希望在给定的确定性目标上,确保所接受的步长满足足够下降条件。而SGD可能需要利用随机梯度的长期统计性质,分析整体优化过程。随机梯度下降不是普通梯度下降的一个完全准确但更便宜的版本,而是一种主动以随机估计换取计算效率的优化方法。第九幕:1958—1960年,当机器第一次被要求根据错误修改自己第56章配图现在,我们来到了梯度下降故事与人工智能真正发生重要交汇的年代。1958年。美国康奈尔航空实验室。研究者:弗兰克·罗森布拉特(Frank Rosenblatt)正在研究一种能够根据输入与反馈调整内部连接的系统。这种系统叫作:Perceptron(感知机)。1958年11月,他在《Psychological Review》发表:The Perceptron: A Probabilistic Model for Information Storage and Organization in the Brain。《感知机:一种关于大脑信息存储与组织的概率模型》。论文第65卷第6期,第386—408页。[PubMed]感知机真的“学习”了吗?在一个最简单的线性分类器里,我们可以使用:z=w⊤x+bz=\mathbf w^\top\mathbf x+bz=w⊤x+b决定输入属于哪一类。参数:w\mathbf ww以及:bbb会影响分类结果。如果当前预测错误,算法可以按照规则修改这些参数。例如,在一种常见的二分类感知机更新表示里:w←w+ηyx\boxed{ \mathbf w\leftarrow\mathbf w+\eta y\mathbf x }w←w+ηyx其中:y∈{−1,+1}y\in\{-1,+1\}y∈{−1,+1}且只在相应的错误分类条件下更新。这种方法的特点是:不需要研究者为每条数据手工规定最终的权重。而是利用训练样本和反馈,逐步调整模型参数。不过,必须区分:经典感知机更新规则,并不等同于对任意光滑神经网络损失函数执行梯度下降。它具有自己的分类目标与更新性质。1958年的感知机,也不是现代深层神经网络的完整版本。1960年:Widrow与Hoff的自适应电路第56章配图1960年,斯坦福大学的:伯纳德·维德罗(Bernard Widrow)。与:马西安·霍夫(Marcian E. Hoff)。发表:Adaptive Switching Circuits《自适应开关电路》。论文出现在当年的IRE WESCON会议记录中。他们研究了通过统计学习调整电路参数的问题。[信息系统实验室][J-GLOBAL]与这条研究路线相关的一项重要算法是:Least Mean Squares(LMS,最小均方)自适应算法。它与梯度下降有非常直接的关系。让一个线性模型根据误差调整参数考虑最简单的一条样本:(x,y)(x,y)(x,y)模型预测:y^=wx\hat y=wxy^=wx定义平方误差:ℓ(w)=12(wx−y)2\ell(w)=\frac12(wx-y)^2ℓ(w)=21(wx−y)2对w求导:dℓdw=(wx−y)x\frac{d\ell}{dw} = (wx-y)xdwdℓ=(wx−y)x梯度下降更新:wnew=w−η(wx−y)xw_{\mathrm{new}} = w-\eta(wx-y)xwnew=w−η(wx−y)x令预测误差:e=y−y^e=y-\hat ye=y−y^得到:wnew=w+ηex\boxed{ w_{\mathrm{new}}=w+\eta ex }wnew=w+ηex这就是LMS类更新规则在单参数情况下的基本形式。对于向量权重:wnew=w+ηex\boxed{ \mathbf w_{\mathrm{new}} = \mathbf w+\eta e\mathbf x }wnew=w+ηex同样成立。这里省略了某些文献对均方误差定义采用不同系数时产生的常数因子;实际实现可以通过学习率约定吸收这项差异。为什么这种更新非常适合工程系统?因为它不需要提前计算整个环境的精确统计分布。系统可以根据当前输入与输出误差,在线调整参数。例如:通信信号中的噪声消除。信道均衡。预测滤波。以及各种自适应信号处理任务。这些研究表明:“机器根据误差调整自身参数”并不是1980年代神经网络才突然出现的思想。它有着统计学、控制与信号处理领域更长的历史。一条重要的分界线到了1960年前后,研究者已经拥有:迭代优化。随机近似。线性分类器的学习规则。以及自适应电路的误差驱动更新。但复杂的多层神经网络还有一个难题。我们可以比较容易地求出最后一层的输出误差。可是,如果网络拥有很多隐藏层,应该怎样知道:前面每一层的每个连接权重,对最终错误究竟贡献了多少?这会将我们带向后来1986年广为人知的反向传播研究。不过,在进入神经网络之前,数学家还要解决另一个问题。如果普通梯度下降在狭长山谷里不断左右摇摆,能不能利用过去的移动历史,使它下降得更快?第十幕:1964年,Polyak让优化算法记住了自己刚才走过的方向第56章配图想象两个人沿着狭长山谷下坡。第一位每走一步,都完全重新观察当前位置的坡度。他只按照当前坡度决定下一步。于是,可能不断从山谷左侧走向右侧。再从右侧走回左侧。第二位则使用另一种策略。他不仅考虑当前坡度,还保留一部分前面运动的方向。如果连续多次朝山谷前进方向移动,就逐渐积累速度。如果梯度不断要求左右改变方向,那么这些相互抵消的成分,可能受到抑制。这种直觉对应一种著名的优化方法:Momentum(动量)。1964年:Boris Polyak1964年,苏联数学家:鲍里斯·波利亚克(Boris T. Polyak)发表:Some Methods of Speeding Up the Convergence of Iteration Methods《加速迭代方法收敛的若干方法》。俄文原文发表于《计算数学和数学物理杂志》第4卷第5期,第791—803页。英文译文发表于《USSR Computational Mathematics and Mathematical Physics》第4卷第5期,第1—17页。[数学网][ScienceDirect]论文研究了如何利用多步迭代加速传统方法,并形成后来通常称作:Heavy-Ball Method(重球法)的重要研究基础。普通梯度下降只记住当前位置xt+1=xt−η∇f(xt)\mathbf x_{t+1} = \mathbf x_t-\eta\nabla f(\mathbf x_t)xt+1=xt−η∇f(xt)当前更新完全由当前位置的梯度决定。Momentum还记住前一步的运动我们引入:vt\mathbf v_tvt表示更新方向的累积量。采用一种常见的动量参数约定:vt+1=βvt+∇f(xt)\boxed{ \mathbf v_{t+1} = \beta\mathbf v_t+\nabla f(\mathbf x_t) }vt+1=βvt+∇f(xt)然后:xt+1=xt−ηvt+1\boxed{ \mathbf x_{t+1} = \mathbf x_t-\eta\mathbf v_{t+1} }xt+1=xt−ηvt+1其中:0≤β<10\le\beta<10≤β<1表示保留多少过去的更新信息。如果:β=0\beta=0β=0那么:vt+1=∇f(xt)\mathbf v_{t+1}=\nabla f(\mathbf x_t)vt+1=∇f(xt)于是就退回普通梯度下降。如果:β=0.9\beta=0.9β=0.9则每一步会保留相当一部分过去的更新方向。另一种等价的重球法表示为:xt+1=xt−η∇f(xt)+β(xt−xt−1)\boxed{ \mathbf x_{t+1} = \mathbf x_t-\eta\nabla f(\mathbf x_t) + \beta(\mathbf x_t-\mathbf x_{t-1}) }xt+1=xt−η∇f(xt)+β(xt−xt−1)这里使用了与上一式一致的参数约定。为什么Momentum可能减少左右摇摆?假设某个坐标方向上的梯度不断改变符号。一会儿是正。一会儿是负。那么,当我们对这些梯度进行带权累积时,相互反向的成分可能部分抵消。而某个持续朝向最优位置的方向,其梯度贡献可能更加一致。因此,动量能够在一些狭长二次型中改善优化轨迹。但必须注意:动量不等于永远更快,也不保证任意学习率和动量系数组合都稳定。如果参数选择不合适,动量也可能造成:更大的超调。明显的震荡。甚至发散。动量到底是什么?它是一种算法机制。不是说神经网络参数真的拥有质量、速度和物理惯性。“重球”是非常有帮助的数学比喻。但其正确性最终取决于迭代公式和收敛分析,而不是物理直觉本身。Polyak的研究说明:有时候,仅仅利用过去几次迭代的信息,就能够改善一个只使用当前梯度的一阶优化方法。这项思想后来成为许多神经网络优化器的组成部分。第十一幕:1983年,Nesterov提出了一个更快的凸优化方法第56章配图到了1980年代,优化理论已经积累了大量关于收敛速度的研究。人们不再只关心:这个算法最终会不会收敛?还开始研究:它要经过多少次迭代,才能接近目标精度?这项问题涉及:Convergence Rate(收敛速率)。1983年:Yurii Nesterov1983年,数学家:尤里·涅斯捷罗夫(Yurii E. Nesterov)发表:A Method of Solving a Convex Programming Problem with Convergence Rate O(1/k²)。《一种具有 O(1/k2)O(1/k^2)O(1/k2) 收敛速率的凸规划求解方法》。这项研究的俄文原文刊登于《苏联科学院报告》,英文译文发表于《Soviet Mathematics Doklady》。[Hengshuai,]为什么论文标题中的平方如此重要?对于一般L-smooth凸目标函数,在适当的初始条件与步长选择下,标准梯度下降可以获得典型的:f(xk)−f(x∗)=O(1k)\boxed{ f(x_k)-f(x^*)=O\left(\frac1k\right) }f(xk)−f(x∗)=O(k1)的目标函数误差上界。而Nesterov的加速方法,在对应假设下能够达到:f(xk)−f(x∗)=O(1k2)\boxed{ f(x_k)-f(x^*)=O\left(\frac1{k^2}\right) }f(xk)−f(x∗)=O(k21)这意味着:当迭代次数增加时,理论上可以获得更快的误差衰减量级。例如,只看这两个渐近表达式中的主要因子:1100=0.01\frac1{100}=0.011001=0.01而:11002=0.0001\frac1{100^2}=0.000110021=0.0001相差100倍。但这只是渐近速率的直观比较。真实优化结果还依赖:初始距离。光滑性常数。算法中的常数项。目标函数类别。以及具体参数。不能直接说:“Nesterov在任何神经网络上都比普通梯度下降快100倍。”一种现代常见的加速梯度表示对于某些光滑凸优化问题,可以使用如下形式表达加速思想:xk+1=yk−η∇f(yk)\boxed{ x_{k+1}=y_k-\eta\nabla f(y_k) }xk+1=yk−η∇f(yk)再通过:yk+1=xk+1+βk(xk+1−xk)\boxed{ y_{k+1} = x_{k+1} + \beta_k(x_{k+1}-x_k) }yk+1=xk+1+βk(xk+1−xk)更新下一次计算梯度的位置。这里:βk\beta_kβk随具体加速方案与迭代次数而变化。直观上,这种方法不一定只在当前已完成的参数点计算梯度,而会在结合此前运动趋势得到的位置评估下一步。因此,经常被形容为:“向前看一步。”不过,这种表述只是帮助理解。1983年论文包含特定的算法构造与证明;今天不同软件框架里被称作Nesterov Momentum的实现,不一定与原论文公式完全相同。加速与稳定之间的微妙关系一个算法能在某种数学条件下拥有更好的最坏情况收敛速率,不等于它在每项实际任务中都必然更快。尤其在神经网络的非凸随机训练环境里:理论假设可能不完全满足。随机梯度噪声可能影响运动路径。某些加速项可能放大震荡。因此,优化器选择仍然需要结合目标结构和实际实验。但1983年的工作标志着一项非常重要的理论进步。优化算法不只是沿着梯度方向下降,也可以通过精心设计的迭代历史组合,提高某些问题上的理论收敛速度。第十二幕:1986年,反向传播为什么让梯度下降真正走进多层神经网络?第56章配图现在,我们终于来到现代人工智能训练史中的一个重要节点。1986年10月9日。《Nature》发表:Learning Representations by Back-Propagating Errors《通过误差反向传播学习表示》。作者是:戴维·鲁梅尔哈特(David E. Rumelhart)。杰弗里·辛顿(Geoffrey E. Hinton)。罗纳德·威廉姆斯(Ronald J. Williams)。论文刊登于第323卷,第533—536页。[Nature]但需要明确:1986年并不是误差反向传播或链式求导历史上的绝对起点。此前已经存在自动微分的研究,以及对多层网络计算导数的相关探索。1986年论文的重要影响,在于系统展示了如何利用误差反向传播,让多层网络中的隐藏单元通过训练形成有用的内部表示,并推动了这一学习方法的广泛传播。梯度下降解决的是“怎样更新”假设模型的全部参数是:θ\boldsymbol\thetaθ损失函数:L(θ)L(\boldsymbol\theta)L(θ)梯度下降告诉我们:θt+1=θt−η∇θL\boxed{ \boldsymbol\theta_{t+1} = \boldsymbol\theta_t- \eta\nabla_\theta L }θt+1=θt−η∇θL但它没有直接回答:如果损失函数由几十层非线性运算复合而成,梯度究竟怎样高效计算?反向传播解决的是“怎样计算梯度”这就是Backpropagation与Gradient Descent之间最重要的职责区别。**反向传播(Backpropagation)**主要是一种利用链式法则,在计算图中高效求导的方法。**梯度下降(Gradient Descent)**则利用求出的梯度,决定怎样修改参数。它们常常一起使用。却不是同一个算法。从最简单的两层计算开始假设:h=w1xh=w_1xh=w1xy^=w2h\hat y=w_2hy^=w2h损失函数:L=12(y^−y)2\boxed{ L=\frac12(\hat y-y)^2 }L=21(y^−y)2现在,我们需要分别求出:∂L∂w1\frac{\partial L}{\partial w_1}∂w1∂L和:∂L∂w2\frac{\partial L}{\partial w_2}∂w2∂L由于:LLL是:w1,w2w_1,w_2w1,w2经过多次运算形成的复合函数,我们可以使用链式法则。对于:w2w_2w2有:∂L∂w2=∂L∂y^∂y^∂w2\frac{\partial L}{\partial w_2} = \frac{\partial L}{\partial\hat y} \frac{\partial\hat y}{\partial w_2}∂w2∂L=∂y^∂L∂w2∂y^所以:∂L∂w2=(y^−y)h\boxed{ \frac{\partial L}{\partial w_2} = (\hat y-y)h }∂w2∂L=(y^−y)h对于:w1w_1w1则需要继续往前传播:∂L∂w1=∂L∂y^∂y^∂h∂h∂w1\frac{\partial L}{\partial w_1} = \frac{\partial L}{\partial\hat y} \frac{\partial\hat y}{\partial h} \frac{\partial h}{\partial w_1}∂w1∂L=∂y^∂L∂h∂y^∂w1∂h得到:∂L∂w1=(y^−y)w2x\boxed{ \frac{\partial L}{\partial w_1} = (\hat y-y)w_2x }∂w1∂L=(y^−y)w2x注意,最终的误差:y^−y\hat y-yy^−y从输出位置开始。逐层向前面的计算节点传播。这便是反向传播思想的最简单表现。图56-5:前向计算与反向梯度传播xhŷL前向:计算预测与损失反向:利用链式法则计算梯度梯度计算完成后,再由优化器更新参数一次真正的数值更新给定:x=2,y=4x=2,\quad y=4x=2,y=4初始参数:w1=0.5,w2=1.5w_1=0.5,\quad w_2=1.5w1=0.5,w2=1.5首先:h=0.5×2=1h=0.5\times2=1h=0.5×2=1预测:y^=1.5×1=1.5\hat y=1.5\times1=1.5y^=1.5×1=1.5误差:y^−y=−2.5\hat y-y=-2.5y^−y=−2.5损失:L=12(−2.5)2=3.125L=\frac12(-2.5)^2=3.125L=21(−2.5)2=3.125反向传播得到:∂L∂w2=−2.5\frac{\partial L}{\partial w_2}=-2.5∂w2∂L=−2.5以及:∂L∂w1=−7.5\frac{\partial L}{\partial w_1}=-7.5∂w1∂L=−7.5如果学习率:η=0.1\eta=0.1η=0.1那么:w1′=0.5−0.1(−7.5)=1.25w_1'=0.5-0.1(-7.5)=1.25w1′=0.5−0.1(−7.5)=1.25w2′=1.5−0.1(−2.5)=1.75w_2'=1.5-0.1(-2.5)=1.75w2′=1.5−0.1(−2.5)=1.75新的预测:y^′=1.25×1.75×2=4.375\hat y'=1.25\times1.75\times2=4.375y^′=1.25×1.75×2=4.375新的损失:L′=12(4.375−4)2L'=\frac12(4.375-4)^2L′=21(4.375−4)2得到:L′=0.0703125\boxed{L'=0.0703125}L′=0.0703125从:3.1253.1253.125下降到约:0.07030.07030.0703只经过了一次参数更新。这里使用的是没有非线性激活的极简网络,仅用于解释链式法则和一次梯度更新。它不能代表多层非线性网络的全部表达能力。反向传播与柯西之间的联系我们现在可以清楚地看到两项不同年代的数学思想怎样合作。1847年的下降思想回答:已知梯度以后,怎样调整变量使目标下降?1986年广为人知的反向传播方法,则展示:对于由大量连接组成的模型,怎样高效计算每个参数对最终损失的影响?于是:反向传播负责计算梯度,优化器负责使用梯度。现代深度学习训练中的大量参数更新,都建立在这项分工之上。但并不是所有神经网络训练都只使用普通SGD,也不是所有机器学习算法都需要反向传播。后续的发展,仍然在不断改进梯度计算与参数更新的方法。第十三幕:2014—2015年,Adam为什么成为现代深度学习中常见的优化器?第56章配图随着神经网络不断扩大,优化问题也变得更加复杂。参数可能有成千上万个。几十万个。几百万个。或者远远更多。不同参数方向可能具有不同的梯度尺度。某些参数经常得到较大的梯度。另一些参数可能很少获得非零梯度。于是,研究者开始探索:能不能为不同参数构造自适应的更新幅度?2014年12月:Adam预印本2014年12月22日,两位研究者:迪德里克·金马(Diederik P. Kingma)。以及:吉米·巴(Jimmy Ba)。提交论文:Adam: A Method for Stochastic Optimization《Adam:一种随机优化方法》。该研究随后发表于2015年的第三届国际学习表征会议(ICLR)。[数字对象标识符]因此,提到Adam的时间时,最好区分:2014年预印本。2015年会议发表。Adam的核心思想Adam使用梯度的一阶矩和二阶原始矩的指数移动平均估计。简化写法是:mt=β1mt−1+(1−β1)gt\boxed{ m_t=\beta_1m_{t-1}+(1-\beta_1)g_t }mt=β1mt−1+(1−β1)gtvt=β2vt−1+(1−β2)gt2\boxed{ v_t=\beta_2v_{t-1}+(1-\beta_2)g_t^2 }vt=β2vt−1+(1−β2)gt2其中:gtg_tgt是当前梯度。平方是按参数分量逐个计算。由于:m0=0,v0=0m_0=0,\quad v_0=0m0=0,v0=0早期的移动平均会存在初始化偏差。因此,Adam还使用偏差修正:m^t=mt1−β1t\hat m_t=\frac{m_t}{1-\beta_1^t}m^t=1−β1tmtv^t=vt1−β2t\hat v_t=\frac{v_t}{1-\beta_2^t}v^t=1−β2tvt然后:θt=θt−1−ηm^tv^t+ε\boxed{ \theta_t= \theta_{t-1} - \eta \frac{\hat m_t}{\sqrt{\hat v_t}+\varepsilon} }θt=θt−1−ηv^t+εm^t分母中的平方根和小常数:ε\varepsilonε帮助调整不同参数方向的更新尺度,并避免零分母。为什么叫作Adam?名字来自:Adaptive Moment Estimation。即:自适应矩估计。它不是因为某个具体名叫Adam的人而命名。Adam是不是永远优于普通梯度下降?不是。Adam在许多实际神经网络任务中非常有用,也常常能够减少一些手工调节学习率尺度的困难。但不能由此断定:Adam对任何目标函数都收敛得更快。或者:Adam永远获得更好的泛化能力。不同优化器的表现依赖:目标函数结构。数据分布。学习率计划。权重衰减方法。批量大小。以及具体训练目标。而且,Adam并不自动消除梯度问题。它仍然需要合理的参数选择与数值实现。Adam与1847年的方法还有关系吗?当然有。它们仍然都属于通过梯度信息调整参数的优化方法。但Adam远比柯西最初的下降方法复杂。它还维护:一阶矩估计。二阶矩估计。偏差修正。以及逐参数的自适应调整。这条历史路线非常清楚。从:寻找局部下降方向。走向:利用随机样本估计梯度。再走向:结合过去的梯度历史与尺度信息进行更新。优化器的设计,本质上是在研究:如何更加有效地利用有限、嘈杂、局部的梯度信息。第十四幕:Python实战——从零实现四种下降算法第56章配图现在,我们将本章全部关键计算,整理成一份可以独立运行的Python程序。它不需要PyTorch。不需要TensorFlow。不需要NumPy。只使用标准库。我们会实现:固定学习率梯度下降。二次函数的精确线搜索。Armijo回溯线搜索。Polyak式动量更新。然后,再用一个最简单的线性回归模型测试随机梯度下降。第一部分:定义目标函数与梯度python复制代码 import math import random def loss(x, y, curvature=8.0): """ 二维正定二次目标函数: f(x,y) = 0.5 * (x*x + curvature*y*y) """ return 0.5 * ( x*x + curvature*y*y ) def gradient(x, y, curvature=8.0): """ ∂f/∂x = x ∂f/∂y = curvature*y """ return x, curvature*y def gradient_descent( start=(-2.4, 1.4), lr=0.1, steps=30, curvature=8.0, ): """ 固定学习率梯度下降。 """ x, y = start history = [] for step in range(steps + 1): history.append({ "step": step, "x": x, "y": y, "loss": loss(x, y, curvature), }) gx, gy = gradient( x, y, curvature ) x -= lr * gx y -= lr * gy if not ( math.isfinite(x) and math.isfinite(y) ): break return history 第二部分:普通梯度下降的三种命运python复制代码 for lr in (0.1, 0.25, 0.3): history = gradient_descent( start=(-2.4, 1.4), lr=lr, steps=15, curvature=8.0, ) final = history[-1] print( f"lr={lr:.2f}", f"x={final['x']:.5f}", f"y={final['y']:.5f}", f"loss={final['loss']:.6f}", ) 因为:0<η<0.250<\eta<0.250<η<0.25是当前二维正定二次函数的固定步长收敛条件,所以:η=0.10\eta=0.10η=0.10应该逐步收敛。而:η=0.25\eta=0.25η=0.25会让y方向保持等幅交替变化。η=0.30\eta=0.30η=0.30则会在y方向发散。第三部分:实现二次函数的精确线搜索对于我们的目标函数:f(x,y)=12(x2+cy2)f(x,y)=\frac12(x^2+cy^2)f(x,y)=21(x2+cy2)海森矩阵是:H=[100c]H= \begin{bmatrix} 1&0\\ 0&c \end{bmatrix}H=[100c]因此:ηt=gx2+gy2gx2+cgy2\eta_t= \frac{g_x^2+g_y^2} {g_x^2+cg_y^2}ηt=gx2+cgy2gx2+gy2可以直接计算。python复制代码 def exact_line_search( start=(-2.4, 1.4), steps=30, curvature=8.0, ): x, y = start history = [] for step in range(steps + 1): history.append(( step, x, y, loss(x, y, curvature) )) gx, gy = gradient(x, y, curvature) numerator = gx*gx + gy*gy if numerator < 1e-20: break denominator = ( gx*gx + curvature*gy*gy ) lr = numerator / denominator x -= lr * gx y -= lr * gy return history result = exact_line_search() for step, x, y, value in result[:8]: print( step, round(x, 5), round(y, 5), round(value, 7) ) 注意,这段代码的学习率公式,只针对我们构造的特定正定二次函数成立。对于任意非线性目标,不能直接照抄同一公式。第四部分:实现Armijo回溯线搜索python复制代码 def armijo_step( x, y, curvature=8.0, initial_lr=1.0, shrink=0.5, sufficient_decrease=1e-4, ): """ 在负梯度方向上执行Armijo回溯线搜索。 使用: f(new) <= f(old) - c*lr*||g||^2 """ gx, gy = gradient(x, y, curvature) norm2 = gx*gx + gy*gy if norm2 < 1e-20: return 0.0 old_loss = loss(x, y, curvature) lr = initial_lr for _ in range(60): nx = x - lr*gx ny = y - lr*gy new_loss = loss( nx, ny, curvature ) threshold = ( old_loss - sufficient_decrease*lr*norm2 ) if new_loss <= threshold: return lr lr *= shrink raise RuntimeError( "回溯线搜索未找到合适步长" ) def descent_with_armijo( start=(-2.4, 1.4), steps=30, ): x, y = start history = [] for step in range(steps + 1): history.append( (step, x, y, loss(x, y)) ) lr = armijo_step(x, y) if lr == 0: break gx, gy = gradient(x, y) x -= lr*gx y -= lr*gy return history history = descent_with_armijo() assert all( history[i+1][3] <= history[i][3] + 1e-12 for i in range(len(history)-1) ) print("Armijo线搜索测试通过") 这项程序展示了一件很重要的事。我们不再要求用户提前为全部迭代指定唯一固定步长。而是每一步根据目标函数当前的形状,检查候选步长是否能够带来足够下降。不过,真实科学计算中,还需要处理:更一般的停止准则。梯度数值误差。约束条件。以及函数或梯度计算本身的成本。第五部分:实现Momentumpython复制代码 def gradient_descent_momentum( start=(-2.4, 1.4), lr=0.06, beta=0.8, steps=30, curvature=8.0, ): x, y = start vx = 0.0 vy = 0.0 history = [] for step in range(steps + 1): history.append({ "step": step, "x": x, "y": y, "loss": loss(x, y, curvature), }) gx, gy = gradient( x, y, curvature ) # 梯度的指数累积 vx = beta * vx + gx vy = beta * vy + gy x -= lr * vx y -= lr * vy return history plain = gradient_descent( lr=0.06, steps=30, ) momentum = gradient_descent_momentum( lr=0.06, beta=0.8, steps=30, ) print("普通GD最终损失:", plain[-1]["loss"]) print("Momentum最终损失:", momentum[-1]["loss"]) 可以通过修改:python复制代码beta=0.5或:python复制代码beta=0.9观察最终结果。但是,这个短小的二次优化实验,不足以证明某个动量参数在所有问题上都是最佳选择。动量的表现与目标函数曲率、学习率和初始条件密切相关。第六部分:随机梯度下降训练线性回归我们再次使用:y^=wx\hat y=wxy^=wx训练数据:text复制代码(1, 2) (2, 4) (3, 6) (4, 8)真实的最佳参数是:w∗=2w^*=2w∗=2python复制代码 def train_sgd( samples, initial_weight=0.0, lr=0.02, steps=400, seed=42, ): rng = random.Random(seed) w = initial_weight history = [] for step in range(steps): x, y = rng.choice(samples) prediction = w * x # 单样本平方损失梯度 grad = (prediction - y) * x w -= lr * grad if step % 20 == 0: history.append((step, w)) return w, history samples = [ (1.0, 2.0), (2.0, 4.0), (3.0, 6.0), (4.0, 8.0), ] weight, history = train_sgd(samples) print("训练得到的w:", weight) for step, w in history: print( f"step={step:3d}, w={w:.6f}" ) assert abs(weight - 2.0) < 1e-3 print("SGD训练完成") 这段代码并没有手工把:w=2w=2w=2直接赋给模型。而是从:w=0w=0w=0开始。反复读取随机样本。计算预测误差。估计梯度。最后更新参数。由于这四条人工数据完全满足:y=2xy=2xy=2x每条样本本身都与相同的最优参数一致,学习过程相对简单。在真实数据包含噪声、存在多个参数、或者目标非凸时,训练轨迹会复杂得多。第七部分:验证手写梯度是否正确最后,增加一项非常实用的算法训练。假设你手工推导了:∇f\nabla f∇f但不确定是否正确。可以使用:Finite Difference(有限差分)进行数值检查。例如,对x方向的偏导数:∂f∂x≈f(x+h,y)−f(x−h,y)2h\frac{\partial f}{\partial x} \approx \frac{f(x+h,y)-f(x-h,y)}{2h}∂x∂f≈2hf(x+h,y)−f(x−h,y)对于y方向:∂f∂y≈f(x,y+h)−f(x,y−h)2h\frac{\partial f}{\partial y} \approx \frac{f(x,y+h)-f(x,y-h)}{2h}∂y∂f≈2hf(x,y+h)−f(x,y−h)实现如下:python复制代码 def numerical_gradient( x, y, curvature=8.0, h=1e-5, ): gx = ( loss(x+h, y, curvature) - loss(x-h, y, curvature) ) / (2*h) gy = ( loss(x, y+h, curvature) - loss(x, y-h, curvature) ) / (2*h) return gx, gy x, y = -1.7, 0.8 analytic = gradient(x, y) numeric = numerical_gradient(x, y) print("解析梯度:", analytic) print("数值梯度:", numeric) assert abs( analytic[0] - numeric[0] ) < 1e-7 assert abs( analytic[1] - numeric[1] ) < 1e-7 print("梯度检查通过") 为什么这项实验重要?因为在现代机器学习中,一些复杂模型的梯度可能由自动微分系统计算。但当我们自行实现特殊算子或损失函数时,仍然可能出现求导错误。数值梯度检查可以帮助发现一部分问题。不过,有限差分也有自己的精度限制。如果:hhh太大,截断误差可能明显。如果:hhh太小,浮点舍入误差又可能影响结果。因此,它是一种有用的调试工具,但不是对任意函数都能给出无限精度的求导方法。第十五幕:如果梯度已经等于零,机器就一定学会了吗?第56章配图非凸目标可能包含多个局部极小值,以及梯度为零但并非最低点的位置。现在,我们已经追踪了从1847年到现代深度学习的优化算法。但是,还有一个问题需要回答。如果某次训练中,梯度已经非常接近零,我们能不能宣布模型已经找到最佳答案?不一定。一个具有两个最低点的函数考虑:f(x)=(x2−1)2\boxed{ f(x)=(x^2-1)^2 }f(x)=(x2−1)2它的函数值永远非负。在:x=−1x=-1x=−1以及:x=1x=1x=1处:f(x)=0f(x)=0f(x)=0因此,这两个位置都是全局最低点。但是,它的导数是:f′(x)=4x(x2−1)\boxed{ f'(x)=4x(x^2-1) }f′(x)=4x(x2−1)现在,假设我们从:x0=0x_0=0x0=0开始。那么:f′(0)=0f'(0)=0f′(0)=0梯度下降更新:x1=0−η×0=0x_1=0-\eta\times0=0x1=0−η×0=0下一次仍然是:x2=0x_2=0x2=0于是,程序永远停在0。可此时:f(0)=1f(0)=1f(0)=1明显高于:f(−1)=f(1)=0f(-1)=f(1)=0f(−1)=f(1)=0梯度已经为零,却没有找到最低点。图56-6:梯度为零的点,不全是最低点1.56250-1.5-1.25-1-0.75-0.5-0.2500.250.50.7511.251.5查看图表数据xf(x)=(x²−1)²-1.51.5625-1.250.31640625-10-0.750.19140625-0.50.5625-0.250.87890625010.250.878906250.50.56250.750.19140625101.250.316406251.51.5625最低点位于−1和1;中间的0同样满足导数为零,却是局部极大点。驻点不等于最优点如果:∇f(x)=0\nabla f(\mathbf x)=0∇f(x)=0我们称:x\mathbf xx是一个:Stationary Point(驻点)。驻点可能是:局部极小值。局部极大值。或者鞍点。例如,在二维函数:f(x,y)=x2−y2f(x,y)=x^2-y^2f(x,y)=x2−y2中:∇f(0,0)=[00]\nabla f(0,0)= \begin{bmatrix} 0\\0 \end{bmatrix}∇f(0,0)=[00]但沿x方向,函数向上弯曲。沿y方向,函数向下弯曲。因此:(0,0)(0,0)(0,0)是一个鞍点。这说明:只要我们处理非凸优化问题,就必须谨慎解释梯度趋近零的含义。训练损失下降,也不等于模型一定有用还有一个更接近机器学习本质的问题。假设我们拥有一千条训练样本。模型不断调整参数。终于将训练集上的损失降到非常低。这当然说明:模型在当前损失定义下,很好地拟合了这些训练数据。但它是否能正确处理没有见过的新数据?仍然需要检查。因为模型可能:记住训练数据中的偶然噪声。利用训练集中特有的规律。或者学到只对当前样本有效的参数组合。这种现象与:Overfitting(过拟合)有关。因此,机器学习通常不仅需要:训练损失。还需要:验证数据。测试数据。以及与实际任务相匹配的评价指标。优化器解决的是怎样降低所定义的损失,而不是自动保证损失函数恰好表达了我们真正希望机器学会的全部能力。从数学走向机器学习,真正增加了什么?在柯西的数学问题里,我们已经有一个需要求解的函数。而在机器学习里,我们还需要解决更前面的问题。应该预测什么?应该使用什么数据?应该怎样构造损失?什么样的模型能够表达目标规律?什么样的训练结果才具有泛化能力?所以,现代机器学习并不只是:将梯度下降运行足够多次。它是一项包含数据、模型、优化和统计评估的完整研究工作。尾声:1847年,柯西并不知道未来会有神经网络1847年10月18日。巴黎。柯西希望寻找一种更加普遍的方法,求解复杂联立方程。他尝试将求解问题转变成一个非负函数的下降问题。他观察到,如果根据偏导数选择合适的小变化量,函数值就有机会降低。于是,未知数可以一步步被修改。每一次修改,都利用当前位置的数学信息。经过反复迭代,函数可能逐渐逼近一个最小值。这种思想看起来十分朴素。但它拥有巨大的延展空间。1951年,Robbins与Monro研究随机观测中的迭代逼近。1952年,Kiefer与Wolfowitz进一步研究随机函数的极值估计。1958年,Rosenblatt研究感知机的学习。1960年,Widrow与Hoff研究能够根据误差调整参数的自适应电路。1964年,Polyak研究怎样利用多步迭代加速收敛。1966年,Armijo研究能够控制下降幅度的变步长方法。1983年,Nesterov发展了具有更好理论速率的凸优化算法。1986年,Rumelhart、Hinton与Williams展示了误差反向传播怎样让多层网络获得可训练的隐藏表示。2014年至2015年,Kingma与Ba提出Adam,将梯度的不同矩信息纳入自适应参数更新。这些研究并非一条没有分叉的单线传承。统计学、优化理论、控制工程、信号处理与神经网络研究,各自拥有复杂的历史。但它们共同推进了一项重要能力。让计算机在无法直接求出最佳参数的情况下,通过反复计算局部信息,逐渐改进自己的行为。本章的五个关键公式1. 普通梯度下降θt+1=θt−η∇L(θt)\boxed{ \theta_{t+1} = \theta_t-\eta\nabla L(\theta_t) }θt+1=θt−η∇L(θt)2. 随机梯度下降θt+1=θt−ηtgt\boxed{ \theta_{t+1} = \theta_t-\eta_tg_t }θt+1=θt−ηtgt其中gₜ通常是根据单条样本或小批量估计的梯度。3. Polyak式动量vt+1=βvt+∇L(θt)\boxed{ v_{t+1}=\beta v_t+\nabla L(\theta_t) }vt+1=βvt+∇L(θt)θt+1=θt−ηvt+1\boxed{ \theta_{t+1}=\theta_t-\eta v_{t+1} }θt+1=θt−ηvt+14. Armijo充分下降条件L(θ+ηd)≤L(θ)+cη∇L(θ)⊤d\boxed{ L(\theta+\eta d) \le L(\theta)+c\eta\nabla L(\theta)^\top d }L(θ+ηd)≤L(θ)+cη∇L(θ)⊤d5. Adam自适应更新θt=θt−1−ηm^tv^t+ε\boxed{ \theta_t= \theta_{t-1} - \eta\frac{\hat m_t}{\sqrt{\hat v_t}+\varepsilon} }θt=θt−1−ηv^t+εm^t这些公式看起来不同。但是,它们都在研究一个共同问题。怎样利用我们目前获得的信息,决定下一次参数应该如何改变?普通梯度下降使用当前梯度。随机梯度下降使用有限样本估计。Momentum结合过去的运动信息。Armijo通过检查实际下降幅度选择步长。Adam进一步利用梯度的一阶和二阶矩估计,调整各参数的更新尺度。优化器变得越来越复杂。但优化的基本目标仍然十分清楚。在给定目标函数与计算资源的约束下,找到更好的参数。第六篇真正的起点到第55章为止,我们主要研究算法怎样处理已经存在的信息。例如:寻找最佳序列比对。搜索相似片段。推断隐藏状态。重建DNA。恢复可能的进化关系。现在,从第56章开始,算法故事的视角发生了变化。我们不再只是要求:根据固定规则处理输入数据。而是开始研究:怎样利用数据,逐步改变算法自身的参数。这就是机器学习最重要的主题之一。但是,机器要学会一项复杂任务,往往不只是更新一个参数。它可能拥有:几百个参数。几百万个参数。甚至更大规模的参数集合。那么,每个参数究竟如何影响最终输出?如果模型包含几十层相互连接的运算,程序又怎样高效计算全部参数的梯度?这正是下一章的任务。历史档案:从最速下降到现代优化器年份研究与人物历史意义1847年10月18日Cauchy,联立方程组的迭代求解最速下降法的重要早期研究1951年9月Robbins与Monro,随机逼近在随机观测条件下研究迭代估计1952年9月Kiefer与Wolfowitz,随机极值估计进一步发展随机函数优化1958年11月Rosenblatt,感知机误差驱动的学习系统研究1960年Widrow与Hoff,自适应电路LMS类自适应学习算法的重要发展1964年Polyak,加速迭代方法重球法与动量优化的重要来源1966年Armijo,梯度法收敛与变步长充分下降与回溯线搜索相关研究1983年Nesterov,加速凸优化发展具有 O(1/k2)O(1/k^2)O(1/k2) 速率的加速方法1986年10月9日Rumelhart、Hinton、Williams,反向传播推动多层神经网络训练与隐藏表示学习2014年12月22日Kingma与Ba,Adam预印本自适应矩估计优化2015年Adam发表于ICLR该优化方法进入广泛研究与实践主要参考文献与历史依据◇1847年 · 柯西的原始下降方法Cauchy — Méthode générale pour la résolution des systèmes d'équations simultanées(英文译本)原论文发表于《Comptes Rendus》第25卷,第536—538页;链接为Richard J. Pulskamp整理的英译文。重点阅读第537页关于负偏导数方向、步长和函数下降的公式。◇1951年 · Robbins–Monro随机逼近A Stochastic Approximation Method《The Annals of Mathematical Statistics》第22卷第3期,第400—407页。◇1952年 · Kiefer–Wolfowitz随机极值估计Stochastic Estimation of the Maximum of a Regression Function《The Annals of Mathematical Statistics》第23卷第3期,第462—466页。研究如何从带噪声的函数观测中迭代估计最优参数。◇1958年 · Rosenblatt感知机The Perceptron: A Probabilistic Model for Information Storage and Organization in the Brain《Psychological Review》第65卷第6期,第386—408页。◇1960年 · Widrow–Hoff自适应电路Adaptive Switching Circuits(原论文PDF)用于核查早期自适应电路与误差驱动的参数调整研究。◇1964年 · Polyak的加速迭代方法Some Methods of Speeding Up the Convergence of Iteration Methods《USSR Computational Mathematics and Mathematical Physics》第4卷第5期,第1—17页。◇1966年 · Armijo线搜索Minimization of Functions Having Lipschitz Continuous First Partial Derivatives(PDF)《Pacific Journal of Mathematics》第16卷第1期。包含变步长梯度方法与收敛分析。◇1983年 · Nesterov加速梯度方法A Method of Solving a Convex Programming Problem with Convergence Rate O(1/k²)(PDF)用于核查具有 O(1/k2)O(1/k^2)O(1/k2) 速率的加速凸优化原始结果及其数学条件。◇1986年 · 多层神经网络反向传播Rumelhart、Hinton、Williams — Learning Representations by Back-Propagating Errors《Nature》第323卷,第533—536页。核查反向传播在多层网络学习与隐藏表示中的重要研究。◇2014—2015年 · AdamKingma & Ba — Adam: A Method for Stochastic Optimization2014年12月提交预印本,2015年发表于ICLR。包含一阶、二阶矩估计与偏差修正方法。**史实与教学重构说明:**1847年柯西论文的标题、页码、会议日期及主要数学推导,依据原论文译本和历史记录核查。后续随机逼近、动量、线搜索、加速梯度、反向传播及Adam的历史叙述,以所列原始论文为依据。山坡行走的故事是数学教学比喻,不是柯西原始论文中的人物现场记录。本章的抛物线、二维狭长山谷、线性回归训练、动量实验和两层网络示例,均为教学构造。它们展示特定函数下可以严格计算的收敛与发散行为,不能直接推广成任意非凸优化问题或大型神经网络的性能保证。下一章预告 · 第六篇 第57章《错误怎样穿越一层层神经元:反向传播算法的故事》第56章配图1970年,芬兰。研究者Seppo Linnainmaa正在研究一种能够自动计算复杂程序导数的方法。他的工作与后来被广泛称为反向模式自动微分的技术具有重要联系。1974年,Paul Werbos在博士论文中研究了反向传播相关思想及其在学习系统中的可能用途。到了1986年,Rumelhart、Hinton与Williams的研究,使多层网络中的误差反向传播受到更加广泛的关注。但真正令人困惑的问题是:如果一张神经网络拥有成千上万条连接,计算机真的需要为每一个参数,重新运行整个网络来估计梯度吗?答案是:不需要。只要正确利用复合函数的链式法则,我们就可以将大量重复的求导计算重新组织起来。先执行一次前向计算。保存必要的中间结果。再从最终损失出发,沿计算图反向传播局部导数。使每个参数逐渐获得属于自己的梯度。下一章,我们将追踪反向模式自动微分和神经网络反向传播的真实发展史,亲手设计一个多层计算图,逐个节点计算梯度,并验证为什么反向传播在拥有大量参数的模型里具有巨大的计算优势。本章解决了“知道梯度后怎样调整参数”;下一章将解决“面对一个复杂网络,怎样高效计算每一个参数的梯度”。——《算法的故事》第二季 · 第六篇《会学习的算法》 · 第56章 完上一章下一章