首页 / 模块 2 · 概率统计、信息论与最优化 / 第 7 课(共 10 课)

凸性与梯度下降——优化的几何

从零到前沿 ML 自学课程 · 阶段0:数学与工具基础 · 能力点:凸性与梯度下降——损失能否真正降下去

前几课我们从概率与信息论里把损失函数"推"了出来:最大似然给了我们交叉熵,MAP 给了我们带正则的目标。可一旦写下 \(L(\theta)\),真正的问题才开始——怎么把它最小化?这一课讲优化的几何:什么样的地形好走(凸性),为什么沿负梯度走最快,以及为什么有的"碗"明明是凸的却走得慢得让人抓狂(病态曲率)。

读完这一课,你将能够

  • 用"弦在曲线上方"和"Hessian 半正定"两套语言判断一个函数是否凸,并解释凸为什么意味着"局部最优即全局最优"。
  • 说清为什么负梯度是最速下降方向,并解释学习率 \(\eta\) 太大/太小各会怎样。
  • 用条件数(Hessian 最大/最小特征值之比)解释梯度下降为什么在狭长山谷里走"之"字形、收敛慢。
  • 用维度直觉解释为什么高维参数空间里临界点几乎都是鞍点、而非坏的局部极小。
  • 纠正"非凸=训不了"的误解,说出深度学习里真正的拦路虎是鞍点、病态曲率、坏初始化与学习率。
  • 在 \(f=\tfrac12(x^2+\gamma y^2)\) 上手算梯度下降,并用 numpy 改条件数观察收敛快慢。

训练,就是优化

把前几课的成果收个口:无论是回归、分类还是生成模型,训练最终都落到一个统一的形式

\[ \min_{\theta}\; L(\theta), \]

其中 \(\theta\) 是模型的所有参数(可能是几个数,也可能是几十亿个数),\(L\) 是损失。"学习"这个浪漫的词,在数学上就是"在 \(\theta\) 的高维空间里找一个让 \(L\) 尽量小的点"。剩下的全是细节:地形长什么样,从哪儿出发,每步迈多大。

直觉。把 \(L(\theta)\) 想象成一片地形,\(\theta\) 是你站的位置,海拔就是损失。你被蒙住眼睛,只能用脚感受脚下的坡度(梯度),想走到最低的谷底。这一课就是研究:什么样的地形容易走到底,什么样的地形会把你困住。

凸集与凸函数:什么是"好地形"

先别急着背定义。我们想要的"好地形"直觉上是:一个碗。不管从哪儿放一颗球,它都会滚到同一个最低点。数学家把这种性质拆成两层:底面的形状(凸集)和碗壁的形状(凸函数)。

凸集:连两点的线段不会"出界"

一个集合 \(C\) 是凸集(convex set),如果对里面任意两点 \(x,y\),连接它们的整条线段也都在 \(C\) 里:

\[ x,y\in C \;\Rightarrow\; \lambda x+(1-\lambda)y\in C,\quad \forall\,\lambda\in[0,1]. \]

约定好一个贯穿全课的读法:\(\lambda\) 是"\(x\) 的份额"——\(\lambda=1\) 时整点落在 \(x\),\(\lambda=0\) 时落在 \(y\),中间按比例滑动。圆盘、实心椭圆、整个 \(\mathbb{R}^n\) 都是凸的;一个月牙形、一个甜甜圈就不是——你能找到两点,它们的连线穿出了集合外面。

凸函数:弦永远在曲线上方

有了凸的"地基",再看碗壁。一个函数 \(f\) 是凸函数(convex function),如果它图像上任意两点之间的弦(割线)都在函数图像的上方或重合

\[ f\big(\lambda x+(1-\lambda)y\big)\;\le\;\lambda f(x)+(1-\lambda)f(y),\quad \forall\,\lambda\in[0,1]. \]

左边是"先取平均位置,再看函数值";右边是"先取两端函数值,再平均"。凸 = 实际曲线 ≤ 直线插值。注意左右两边的 \(\lambda\) 配的始终是同一个点——\(\lambda\) 越大,无论是位置还是函数值都更靠近 \(x\) 这一端,两边永远对齐,不会错位。抛物线 \(x^2\)、指数 \(e^x\)、绝对值 \(|x|\) 都满足;而 \(\sin x\) 或者有两个谷的函数就不满足——某些弦会钻到曲线下面去。

凸函数与非凸函数对比:弦在曲线上方为凸(唯一谷底),弦可在曲线下方为非凸(多个局部极小) 凸函数 (convex) 非凸函数 (non-convex) 唯一谷底 弦穿到曲线下方 局部极小 全局极小 困住的球 弦在曲线上方 → 凸 → 唯一谷底 弦可在曲线下方 → 非凸 → 多个谷/假谷底
凸 vs 非凸:左图凸函数,任取两点连成的弦(虚线)整段落在曲线上方,且只有一个谷;右图非凸函数有多个谷和一个鞍状起伏,某些弦会钻到曲线下方,于是出现会困住球的局部极小。

直觉。"弦在上方"为什么重要?因为它排除了"中间凹下去一块"的可能。如果中间能凹下去,那块凹陷就可能形成第二个谷——一个会困住球的坑。凸函数从定义上就杜绝了这种坑,所以它最多只有一个谷。

二阶判据:Hessian 半正定(呼应 M1 第7课)

"弦在上方"很直观,但拿到一个具体函数怎么快速判断?这就要请出我们在模块1学过的 Hessian 矩阵 \(H\)(二阶偏导构成的对称矩阵,记录了曲面在每个方向上的弯曲程度)。一维情形大家熟悉:\(f''(x)\ge 0\)(处处不向下弯)就凸。多维的推广是:

\[ f \text{ 凸} \quad\Longleftrightarrow\quad H(\theta)\succeq 0\ \text{处处成立(Hessian 半正定)}. \]

"半正定 \(\succeq 0\)"在模块1第4/5课讲过:等价于 \(H\) 的所有特征值都 \(\ge 0\)。几何上,特征值是各主方向的"弯曲强度"。全部 \(\ge 0\),意味着无论朝哪个方向看,曲面都不向下弯——这正是"碗"的样子。如果某个特征值是负的,那个方向就是向下弯的,曲面在该方向像个鞍——不再是碗。

例题:用 Hessian 判断二次函数是否凸

判断 \(f(x,y)=2x^2+3y^2-2xy\) 是否凸。

解。先求一阶偏导:\(\partial_x f = 4x-2y\),\(\partial_y f = 6y-2x\)。再求二阶:

\[ H=\begin{bmatrix} \partial_{xx} & \partial_{xy}\\ \partial_{yx} & \partial_{yy}\end{bmatrix} =\begin{bmatrix} 4 & -2\\ -2 & 6\end{bmatrix}. \]

正定有个不必算特征值的捷径——顺序主子式法(顺序主子式全为正即正定):左上角 \(4>0\);整个行列式 \(\det H = 4\cdot 6-(-2)(-2)=24-4=20>0\)。两个顺序主子式都为正 ⇒ \(H\) 正定 ⇒ 特征值都 \(>0\)(实际为 \(2.76\) 与 \(7.24\))⇒ \(f\) 严格凸。

注意 Hessian 是常数矩阵(二次函数的二阶导不含变量),所以"处处正定"一次就验完——这正是二次函数好分析的原因。

两点小提醒(看完即可放过)。其一,顺序主子式全为正只能判正定;要判"半正定"(特征值 \(\ge 0\) 而非 \(>0\))则需用所有主子式或直接看特征值,顺序主子式那套对半正定不成立。其二,我们这里只用到"正定 ⇒ 严格凸"这一个方向;反过来不一定成立——比如 \(x^4\) 是严格凸的,但它在原点的二阶导恰好为 \(0\)(并非处处正定)。

关键结论:凸的最大好处——局部最优即全局最优

凸函数最值钱的性质是:任何局部最优都是全局最优。直觉证明:假设 \(\theta^\star\) 是个局部最低点,但别处有个更低的点 \(\theta'\)(\(L(\theta')线段上每一个中间点的函数值都严格低于 \(L(\theta^\star)\)。换句话说,\(\theta^\star\) 旁边就有比它更低的点——这跟"\(\theta^\star\) 是局部最低(周围都更高)"直接矛盾。所以更低的点不存在。一句话:凸地形里没有"假谷底",你脚下感觉到的最低点就是真正的最低点。这就是为什么凸问题"好优化"——梯度下降只要走到坡度为零的地方,就一定到家了。

负梯度 = 最速下降方向(呼应 M1 第6课)

知道了好地形长什么样,现在问:站在地形上某点,往哪个方向迈一步下降最快?答案是负梯度方向 \(-\nabla L\)。回忆模块1第6课的一阶展开,朝单位方向 \(u\) 走一小步 \(\epsilon\):

\[ L(\theta+\epsilon u)\approx L(\theta)+\epsilon\,\nabla L(\theta)^\top u. \]

下降量由 \(\nabla L^\top u\)(梯度与方向的内积)决定。要让函数下降最多,就要让这个内积最负。内积 \(=\|\nabla L\|\,\|u\|\cos\angle\),在 \(\|u\|=1\) 下,当 \(u\) 与 \(\nabla L\) 方向正好相反(\(\cos=-1\))时最负。所以最速下降方向就是 \(u=-\nabla L/\|\nabla L\|\)。梯度指向上坡最陡的方向,取个负号就是下坡最陡的方向。

负梯度方向即最速下降方向谷底 min L∇L上坡最陡−∇L下坡最陡=更新方向θη 步长等高线切向梯度⊥等高线:沿 −∇L 迈一步 η,朝谷底下降
负梯度=最速下降:椭圆等高线上某点处,梯度箭头垂直于等高线指向上坡(损失增大)方向,取负号 -∇L 指向下坡最陡方向;梯度下降每步沿 -∇L 迈一步 η。

把这个想法变成迭代算法,就是梯度下降(gradient descent)

\[ \boxed{\;\theta \leftarrow \theta-\eta\,\nabla L(\theta)\;} \]

每一步朝当前最陡的下坡方向迈一步,步长由学习率(learning rate)\(\eta\) 控制。注意"最速下降"只是局部最优方向——它只看脚下这一小步,不保证是通往谷底的全局捷径(下面的"之"字形就是这个局部性付出的代价)。

学习率 \(\eta\):太大震荡/发散,太小太慢

\(\eta\) 是这一课最需要手感的旋钮。它控制每步迈多远,而"多远算合适"取决于地形的弯曲程度。

对二次碗 \(f=\tfrac12 a\theta^2\)(曲率 \(a\)),一步更新是 \(\theta\leftarrow\theta-\eta a\theta=(1-\eta a)\theta\)。要收敛必须 \(|1-\eta a|<1\),即 \(0<\eta<2/a\)。曲率越大(碗越陡),可用的学习率上限越低。记住这个 \(2/a\)——在多维里,\(a\) 就是某个方向上的曲率,也就是 Hessian 的一个特征值;最严格的红线由最大特征值决定,所以下面会写成 \(\eta<2/\lambda_{\max}\)。它马上要解释病态问题。

易错。很多人把"loss 没降下来"一律归咎于"模型不行/数据不行",其实头号嫌疑往往是 \(\eta\)。\(\eta\) 太大时 loss 会上下剧烈跳动甚至变成 NaN;太小时 loss 平滑但几乎不动。看 loss 曲线的形状,就能反推 \(\eta\) 调高还是调低——这是最便宜的诊断。

病态与条件数:凸碗也能很难走(呼应 M1 第4/5课)

这里是全课最关键的洞察。我们刚说凸问题"好优化",但"好"指的是"不会卡在假谷底",不等于"走得快"。即使地形是个完美的凸碗,如果这碗又长又窄,梯度下降照样会走得很惨。

条件数:碗有多"歪"

衡量碗"歪不歪"的量叫条件数(condition number),定义为 Hessian 的最大与最小特征值之比:

\[ \kappa=\frac{\lambda_{\max}(H)}{\lambda_{\min}(H)}. \]

回忆模块1:特征值是各主方向的曲率。\(\kappa=1\) 意味着各方向曲率一样——等高线是正圆,碗很"圆正"。\(\kappa\) 很大意味着某方向陡得多、某方向缓得多——等高线是狭长的椭圆,一条又深又窄的山谷。这种碗叫病态(ill-conditioned)

条件数对梯度下降的影响:圆形山谷直奔谷底 vs 狭长山谷之字形收敛慢 谷底 起点 κ = 1 圆形 负梯度直指圆心 · 几步直奔谷底 山谷长轴 谷底 起点 κ ≫ 1 狭长山谷 之字形来回反弹 · 沿谷底收敛慢
病态对比:左图条件数κ=1,等高线是正圆,负梯度直指圆心,梯度下降几步直奔谷底;右图κ大,等高线是狭长椭圆,负梯度几乎垂直于山谷长轴,轨迹在两壁间来回反弹走出之字形,沿谷底缓慢推进。

狭长山谷里的"之"字形

为什么病态会拖慢梯度下降?因为负梯度方向通常并不指向谷底。在狭长椭圆里,梯度主要垂直于山谷长轴(朝陡的方向),只有很小一点分量沿长轴(朝谷底)。结果是:你大步横跨山谷、在两侧壁来回反弹(之字形),却只极慢地沿着谷底往前蹭。

更糟的是学习率被"卡死":为了在陡方向不发散,\(\eta\) 必须 \(<2/\lambda_{\max}\);可这么小的 \(\eta\) 在缓方向上每步只挪 \(\eta\lambda_{\min}\) 那么一丁点。收敛步数大致正比于 \(\kappa\):条件数翻倍,要走的步数也大致翻倍。

例题:在病态二次型上手算两步梯度下降

取 \(f(x,y)=\tfrac12(x^2+\gamma y^2)\),\(\gamma=10\)(于是 \(H=\mathrm{diag}(1,10)\),\(\kappa=10\))。梯度 \(\nabla f=(x,\;\gamma y)\)。从 \((1,1)\) 出发,取 \(\eta=0.18\),手算两步:

第 1 步. 当前 \((1,1)\),梯度 \((1,\;10\cdot 1)=(1,10)\)。更新:

\[ (x,y)\leftarrow(1,1)-0.18\,(1,10)=(0.82,\,-0.80). \]

注意 \(y\) 从 \(+1\) 一下被甩到 \(-0.80\)——跨过了谷底(\(y=0\))跳到对面。这就是之字形的一步。

第 2 步. 当前 \((0.82,-0.80)\),梯度 \((0.82,\;10\cdot(-0.80))=(0.82,\,-8.0)\)。更新:

\[ (x,y)\leftarrow(0.82,-0.80)-0.18\,(0.82,-8.0)=(0.6724,\,0.64). \]

\(y\) 又从 \(-0.80\) 弹回 \(+0.64\)——在山谷两侧来回横跳。对比 \(x\) 方向:\(1\to0.82\to0.6724\),老老实实单调下降,但慢吞吞。陡方向(\(y\))剧烈震荡、缓方向(\(x\))龟速前进,这就是病态的全部痛苦。

(若把 \(\eta\) 调到 \(0.2=2/\lambda_{\max}\),\(y\) 方向会变成 \(1\to-1\to1\) 永远反弹不收敛;再大就发散。这印证了 \(\eta<2/\lambda_{\max}\) 的红线。)

ML 和 ML 的联系

病态不是教科书里的人造怪物,它在真实训练里无处不在:不同参数的尺度天差地别、特征没归一化、深层网络里梯度在层间被反复缩放——都会让损失曲面变成狭长山谷。这正是下一课要讲的自适应优化器(动量、RMSProp、Adam)存在的根本理由:它们本质上都是在"偷偷估计曲率、给每个方向配不同的有效学习率",从而抹平病态、把之字形掰直。所以"为什么需要 Adam"这个问题,答案就藏在条件数 \(\kappa\) 里。

深度学习是非凸的——但敌人不是非凸本身

坏消息先说:神经网络的损失 \(L(\theta)\) 几乎从不凸。激活函数的非线性、层层复合,让损失曲面布满起伏。按"凸才好优化"的逻辑,深度学习似乎根本没法训。可它偏偏训得很好。为什么?

关键在于高维空间的几何反直觉。我们的恐惧来自低维想象:非凸 = 一堆坑,球会卡在某个不够深的坑(坏的局部极小)里出不来。但在百万维参数空间里,这个图像是错的。

鞍点示意:x²−y² 马鞍面,x 方向上弯成谷、y 方向下弯成脊 x y z = f 向上弯 λ=+ 谷 向下弯 λ=− 脊 临界点 梯度 = 0 被拉回 被推开 x 方向:上弯,谷,把球拉回 y 方向:下弯,脊,把球推开 高维:要全部方向都向上弯才是坏局部极小 → 极罕见 有上有下的鞍点 → 压倒性常见
鞍点示意:马鞍形曲面 f=x²−y²,沿x方向是向上弯的谷(特征值+),沿y方向是向下弯的脊(特征值−)。高维中临界点几乎都是这种有上有下的鞍点,而非各方向都向上弯的坏局部极小。

一个临界点(梯度为零处)是"坏局部极小",要求 Hessian 在所有方向都向上弯(全部特征值 \(>0\))。而它是鞍点(saddle point),只要存在一个向上弯、一个向下弯的方向(特征值有正有负)。在 \(d\) 维空间里,"每个方向都恰好向上弯"就像连抛 \(d\) 次硬币全是正面——维度越高越罕见(这只是个抓直觉的类比,背后"各方向曲率符号近似独立"的严格分布属于随机矩阵理论,留到 skip)。所以高维里临界点压倒性地是鞍点,而不是坏的局部极小。另外,在很多实际网络里还观察到:越深的(损失越高的)局部极小越稀少,大多数局部极小的损失都彼此接近、且接近全局最优——卡在一个"差很多的谷"里的概率其实很低(这是经验规律,成立与否依赖具体模型与假设,并非铁律,边界留到 skip)。

例题:一个最简单的鞍点

看 \(f(x,y)=x^2-y^2\),临界点在原点。Hessian \(H=\mathrm{diag}(2,-2)\),特征值 \(+2\)(\(x\) 方向向上弯,是个谷)和 \(-2\)(\(y\) 方向向下弯,是个脊)。有正有负 ⇒ 鞍点。沿 \(x\) 轴它是最小值,沿 \(y\) 轴它是最大值——像马鞍。

逃离有多快?在这个标准(非退化)鞍点上,下弯方向 \(y\) 的更新是 \(y\leftarrow(1+2\eta)y\),乘的是一个大于 \(1\) 的因子,是指数放大——只要初始 \(y\) 不恰好为零,迟早会被迅速甩离原点(练习3 正是演示这一点)。所以纯二次鞍点其实逃得挺快。真正让训练"磨蹭很久"的,是另一类:Hessian 在多个方向特征值都 \(\approx 0\) 的平坦/退化鞍点与平台区——那里下弯方向的曲率极小,指数放大的因子非常接近 \(1\),前期看上去几乎停滞,要积累很多步才动起来。换句话说,逃离速度取决于负曲率的强度和初始扰动的大小:曲率越平、扰动越小,看似卡得越久。

关键结论:真正的难点是什么

请把"非凸 = 训不了"这个恐惧删掉。深度学习能成立的经验事实是:非凸本身不可怕,可怕的是——①鞍点(高维里远比坏局部极小常见;标准鞍点逃得快,但平坦/退化的鞍点与平台会让训练长期磨蹭);②病态曲率(之字形,前面那套条件数的故事在非凸地形里照样成立);③坏初始化(出发点决定你掉进哪片地形);④学习率(永远的头号旋钮)。下一课的优化器、和后面要学的初始化/归一化技巧,全都是冲着这四个敌人去的——而没有一个是冲着"消灭非凸"去的。

两个必须记住的凸例子

虽然深度模型非凸,但机器学习的两个基石问题是的,它们是理解一切的脚手架:

调一调,观察现象

下面用 numpy 在 \(f=\tfrac12(x^2+\gamma y^2)\) 上跑梯度下降。改三个旋钮,亲眼看到上面讲的每个结论。每段都能几秒跑完,只 import numpy、只用 print。

任务 1:调条件数 \(\gamma\),看收敛步数

改什么 → 把 \(\gamma\) 从 1 改到 10 再到 50(用各自安全的 \(\eta=1/\gamma\))。预期看到 → 到达 \(\|\theta\|<10^{-3}\) 所需步数随 \(\gamma\) 暴涨:\(\gamma=1\) 约 1 步、\(\gamma=10\) 约 66 步、\(\gamma=50\) 约 342 步。注意 → \(\gamma=1\) 那个"1 步"是个退化巧合:此时 \(\eta=1/\gamma=1\) 恰好等于 \(1/\lambda\),更新变成 \(\theta\leftarrow(1-1)\theta=0\),一步精确落到原点,并不代表"\(\kappa=1\) 所以快"。真正体现"步数 ≈ 正比于 \(\kappa\)"的是 \(\gamma=10\) 与 \(50\) 这两点(\(66\) 与 \(342\),比值约 \(1:5\),正好对上 \(\kappa\) 的 \(10:50\))。为什么 → 条件数 \(\kappa=\gamma\),收敛步数大致正比于 \(\kappa\),病态直接拖慢全局。

import numpy as np

def run(gamma, eta, x0=(1.0, 1.0), tol=1e-3, max_steps=10000):
    x = np.array(x0, dtype=float)
    for k in range(1, max_steps + 1):
        grad = np.array([x[0], gamma * x[1]])   # 梯度 (x, gamma*y)
        x = x - eta * grad                       # theta <- theta - eta * grad
        if np.linalg.norm(x) < tol:
            return k
    return max_steps

for gamma in [1.0, 10.0, 50.0]:
    eta = 1.0 / gamma            # 安全步长,约 1/lambda_max
    print(f"gamma={gamma:5}  cond={gamma:.0f}  steps={run(gamma, eta)}")

任务 2:打印轨迹,亲眼看"之"字形

改什么 → 固定 \(\gamma=10,\ \eta=0.18\),从 \((1,1)\) 出发,打印前几步的 \((x,y)\)。预期看到 → \(y\) 列正负来回横跳(\(1\to-0.80\to0.64\to\dots\)),\(x\) 列单调缓降(\(1\to0.82\to0.6724\to\dots\))。为什么 → 陡方向 \(y\) 跨过谷底来回反弹,缓方向 \(x\) 龟速前进——这就是病态的"之"字形,和例题手算完全一致。

import numpy as np

gamma, eta = 10.0, 0.18
x = np.array([1.0, 1.0])
print("step  x        y")
for k in range(6):
    print(f"{k:3}  {x[0]: .4f}  {x[1]: .4f}")
    grad = np.array([x[0], gamma * x[1]])
    x = x - eta * grad

任务 3:把 \(\eta\) 推过红线,看震荡与发散

改什么 → 固定 \(\gamma=10\)(\(\lambda_{\max}=10\),红线 \(\eta=2/10=0.2\))。依次试 \(\eta=0.15\)(收敛)、\(\eta=0.2\)(恰好反弹不收敛)、\(\eta=0.21\)(发散)。预期看到 → 看的是"降 / 不降 / 爆"这三种定性形态,不是绝对到零:\(\eta=0.15\) 时范数单调缩小、40 步降到约 \(1.5\times10^{-3}\) 量级(还没到极小,因为这点收敛本就要 60 多步);\(\eta=0.2\) 时 \(y\) 在 \(\pm1\) 间永远反弹、范数卡在 \(1.0\) 不降;\(\eta=0.21\) 时范数爆炸到约 \(4.5\times10^{1}\)。为什么 → 收敛要求 \(|1-\eta\lambda_{\max}|<1\),即 \(\eta<2/\lambda_{\max}=0.2\),跨过就停止收敛、再大就发散。

import numpy as np

gamma = 10.0
for eta in [0.15, 0.20, 0.21]:
    x = np.array([1.0, 1.0])
    for _ in range(40):
        x = x - eta * np.array([x[0], gamma * x[1]])
    print(f"eta={eta:.2f}  final ||theta||={np.linalg.norm(x):.3e}")

动手练习

  1. 手验凸性。对 \(f(x,y)=x^2+4y^2+xy\),手算 Hessian,用顺序主子式判断是否(严格)凸(提示:左上 \(2>0\),\(\det=2\cdot8-1=15>0\),故正定),再用 numpy 的 np.linalg.eigvalsh 验证特征值都为正。
  2. 测量条件数与步数的正比关系。基于任务 1 的 run,对 \(\gamma\in\{2,5,10,20,40\}\) 各用 \(\eta=1/\gamma\) 跑一遍,打印 (gamma, steps),观察 steps 是否大致随 \(\gamma\) 线性增长。(提示:别把 \(\gamma=1\) 那个 1 步的退化点混进来比,它是 \(\eta\) 恰好等于精确解步长的特例;从 \(\gamma=2\) 起看线性趋势才靠谱。)
  3. 逃离鞍点。在 \(f(x,y)=x^2-y^2\)(梯度 \((2x,-2y)\))上从 \((0.5,\,10^{-6})\) 出发跑梯度下降,打印 \(y\) 随步数的变化。\(y\) 会按 \((1+2\eta)\) 的因子被指数放大、最终逃离原点——体会"沿下弯方向被指数推开"的过程(初始 \(y\) 越小,前期看似停滞越久,一旦起来就很快)。把初始 \(y\) 设成精确的 \(0\) 会怎样?为什么?
  4. 归一化能治病态。构造 \(f=\tfrac12(x^2+100y^2)\)(\(\kappa=100\))。先直接跑,记下步数;再做变量替换 \(y'=10y\)(即在 \(y\) 方向把尺度缩小 10 倍),让新问题变成 \(\tfrac12(x^2+y'^2)\)(\(\kappa=1\)),再跑,对比步数。这就是特征标准化的威力。

掌握自检

下一课我们就把这一课的诊断变成药方:实战优化器——SGD、动量、Adam 与学习率调度。你会看到动量如何借惯性穿过之字形,Adam 如何给每个方向配自适应步长来对抗病态——这一课埋下的每个 \(\kappa\)、每个红线 \(2/\lambda_{\max}\),都会在那里得到回应。