
实话讲我整理 18.065 的 note3第19到24讲时一开始挺不适应的——前面十几讲都在教我怎么用 SVD、主成分分析、图拉普拉斯这些矩阵工具去“看”数据突然话锋一转开始讲梯度下降、随机梯度下降、动量法感觉像误入了另一门优化课。但等我啃完这六讲才发现它哪里是换了领域它是把前面所有线性代数的储备一次性用到了“如何把最小化问题算出来”这个终极问题上。这份笔记适合谁我觉得特别适合三类人第一类是看过很多优化器博客知道 momentum、Adam 的公式却不理解它们为什么长那样第二类是学完线性代数但不知道特征值、奇异值除了做题还能干嘛的同学第三类是在实际训练模型中被“学习率怎么调、要不要开动量”折磨过的人。如果你在这三类里第19-24讲会给你一层底层解释——优化算法的快慢和稳定性几乎全由矩阵的谱决定。1. 为什么这门矩阵方法课最后讲起了优化算法1.1 从 SVD、图拉普拉斯到“找最小值”的跳跃前十几讲的主线很明确数据分析里的矩阵工具。从 SVD 讲到主成分分析再到随机矩阵、图拉普拉斯、傅里叶最后落到神经网络里矩阵扮演的角色。但到了第19讲课上的问题突然变成了“现在给你一个目标函数你怎么找到它的最小值”第一反应确实会问这不应该是凸优化课的内容吗等我把接下来的内容顺着听下来才明白它的逻辑优化算法自己就是一个迭代矩阵过程。每一次迭代相当于在反复乘同一个矩阵只是这个矩阵会随着当前位置变化而变化。所以梯度的模长怎么衰减、会不会振荡、能不能加速背后全是矩阵特征值和奇异值在指挥。换个角度想这门课前面的所有章节都在做同一件事把数据变成矩阵再从矩阵里提取结构。而优化部分处理的对象恰好是“损失函数的海森矩阵”或“梯度协方差矩阵”。也就是说优化算法并不属于另一个世界它是矩阵方法在“求解”这一环节的自然延伸。1.2 条件数才是隐藏主角这里有个关键线索这门课讲 SVD 时反复强调过条件数也就是最大奇异值除最小奇异值。图像压缩里它决定保留多少奇异值PCA 里它决定主成分的能量分布谱聚类里它和图连通性绑定。到了优化部分条件数依然是主角只是换成了海森矩阵或数据协方差矩阵的谱。普通梯度下降在病态二次型上的收敛速度几乎只由条件数决定条件数越大收敛越慢。而后面讲的各种“加速技巧”比如预处理、动量法、批归一化本质上都在做同一件事压缩条件数。所以这一整段笔记的主线非常清楚我甚至给它起了个名字叫“条件数的复仇”——前面你学过的所有矩阵工具都在这里等着派上用场。2. 梯度下降的收敛速度其实是一张矩阵谱的图2.1 二次型目标函数优化算法的最小实验台要看清梯度下降的收敛行为最好别一上来就看深度学习的复杂损失先落到最简单但又能体现谱影响的函数上f(x) 1/2 · xᵀAx - bᵀx其中 A 是对称正定矩阵。梯度就是 ∇f Ax - b最优点 x* A⁻¹b。梯度下降写成迭代式x_{k1} x_k - t · (A x_k - b)令误差 e_k x_k - x*就可以消掉 b得到最关键的关系e_{k1} (I - tA) e_k这一步是整个分析的钥匙。你把“梯度下降算法”看成一种操作迭代过程就变成了纯矩阵作用。后面所有关于收敛的分析都在围绕这个小矩阵展开它必须有小于 1 的谱半径才收敛谱半径越小收敛越快。2.2 特征值差距大时为什么最速下降会走锯齿“最速下降”这个名字挺误导人的每一步走的是局部最陡方向整体却并不快。一个经典的二维例子是 A [[1,0],[0,100]]等高线是又扁又长的椭圆。梯度方向基本垂直等高线但椭圆长短轴方向的特征值相差 100 倍于是从某个点出发会一路以锯齿状路径跌跌撞撞走向中心。出现锯齿的原因很简单步长 t 只能取一个全局值。对 λ 1 的方向合适的步长对 λ 100 的方向而言太小对 λ 100 合适的步长对 λ 1 的方向又超过 2/λ 导致发散。于是只能折中两边都凑合结果就是整体收敛率非常差。这个收敛因子可以精确算出来((κ-1)/(κ1))²其中 κ λ_max / λ_min。κ 100 时收敛因子大约是 0.96每一步只能把误差缩小约 4%慢到让人怀疑程序出了 bug。2.3 步长的选择本质上是谱半径最小化问题把步长选择当成一个优化问题思路会清楚很多。对固定的 t矩阵 I - tA 的特征值是 1 - t·λ_i它们绝对值的最大值叫谱半径ρ max_i |1 - t·λ_i|只要 ρ 1迭代就收敛ρ 越接近 0收敛越快。如果知道 A 的特征值范围 [λ_min, λ_max]最优 t 会把最大和最小特征方向的 |1 - tλ| 拉平也就是t* 2 / (λ_min λ_max)对应的最优谱半径是ρ* (κ - 1) / (κ 1)从这个公式能直接解释“学习率太大直接发散”当 t 2/λ_max 时最大特征方向满足 |1 - t·λ_max| 1误差在那个方向被持续放大发散是必然结果。所以调学习率不是玄学它按定义就是一个谱半径最小化问题。3. 随机梯度下降噪声不是坏事谱里藏着原因3.1 小批量梯度的无偏估计与协方差矩阵理解 SGD 的关键是把目标函数看成每个样本损失的平均。真实梯度是全体样本梯度的平均而 SGD 用小批量样本的梯度均值代替它。这个估计是无偏的抽样均匀时小批量梯度的期望等于全量梯度。但无偏不意味着没方差。它围绕真实梯度有一圈波动这个波动的大小用梯度向量的协方差矩阵 C 来衡量C E[(g_i - g)(g_i - g)ᵀ]为什么这是线性代数内容因为 C 经常正比于数据协方差矩阵或其低秩近似而数据协方差的谱又正好是数据矩阵奇异值的平方。也就是说前面 SVD 章节里学的奇异值谱在这里直接决定了 SGD 的噪声水平。3.2 从鞍点上“蹦出去”谱层面的解释很多资料说“SGD 的噪声能帮助逃离鞍点”听起来有点玄。其实从谱的角度看并不复杂把损失函数在鞍点附近做二阶展开海森矩阵有正特征方向也有负特征方向。在鞍点附近梯度模长很小确定性梯度下降基本在原地踏步每一步只能走一点点。但 SGD 的梯度估计含随机噪声相当于每一步叠加了一个随机位移。即使目标函数在某个方向上是平的噪声也有能量能让你“漂移”到非零梯度的区域。海森矩阵越平的方向梯度噪声越容易起主导作用。所以噪声的作用有点像在冰面上被风一直吹着移动——你未必知道风往哪吹但时间足够长时总能滑出这片平台。3.3 学习率衰减的线性代数依据SGD 想收敛学习率不能固定。直觉上固定学习率会在极小值附近保持一个与步长相当的振荡半径稳态误差归不了零。理论上要求∑ t_k ∞保证算法在无穷时间上能到达目标附近∑ t_k² ∞保证随机噪声的累积不爆炸。经典的方案是 t_k t0 / (1 γk)。放到矩阵谱的语境里衰减速度应该匹配目标附近海森矩阵的特征值大小。如果主要特征值很大前期的 t0 必须小否则直接发散如果谱非常分散只用单一 t0 很难兼顾这时常见做法是先用 warmup 平滑上升再走余弦衰减到接近零。我在实际调参时一般先跑几十个 iteration 观察损失是否下降把 t0 的量级定下来再套用 cosine schedule而不是一开始就调衰减系数。4. 动量法与 Nesterov 加速二阶差分方程把收敛率拉上一个台阶4.1 从一阶迭代到二阶迭代引入速度变量普通梯度下降的误差递推是一阶差分方程e_{k1} (I - tA) e_k每一步只由前一步决定。动量法引入速度变量 v用来累积此前的梯度方向v_{k1} β·v_k ∇f(x_k) x_{k1} x_k - t·v_{k1}从状态空间看它把一阶迭代变成了二阶差分方程系统有了“惯性”。这个惯性在特征值分散的问题里很有用当某个方向梯度符号不断变化、剧烈振荡时速度可以抵消往复的抖动保留一致的前进方向。更准确地说动量迭代对应的矩阵会拥有复数特征值让轨迹带有旋转和阻尼。参数选得好时这些复数特征值全部落在单位圆内而且总和半径更小。4.2 Chebyshev 多项式为什么加速理论上限那么漂亮对二次型目标动量法不是随便走走。经过几步递推误差可以写成e_k P_k(A) · e_0其中 P_k 是次数不超过 k 的多项式且满足 P_k(0) 1。我们希望这个多项式在 A 的所有特征值上都尽量小而恰好这个问题有精确的最优解需要用 Chebyshev 多项式来逼近。Chebyshev 多项式 T_k(z) 在 z ∈ [-1,1] 区间内就是 cos(k·arccos z)区间外会用双曲余弦快速放大。把 [-1,1] 映射到 A 的特征值区间再截断最大项就能导出动量的最优 β 和步长组合。最终的有效收缩率大约对应 1/√κ而普通梯度是 1/κ。举个具体例子κ 100 时普通梯度每步只能缩小约 4%而动量法可以把每步误差的几何平均降到 0.8 倍附近差距一个数量级。Nesterov 加速方法在凸问题上能达到 O(1/k²) 的收敛率根源就在这里。课上推导了很大篇幅最后核心直觉倒是很简单二阶迭代允许你使用 Chebyshev 多项式指示的振荡节奏从而显著压缩谱的影响。4.3 稳定性边界β 过大会螺旋发散的谱判据动量法不是越猛越好。把 (x_k, v_k) 合成一个增广状态迭代矩阵会变成一个 2×2 的分块矩阵。要稳定这个增广矩阵所有特征值的模都必须小于 1。β 太小时退化成普通梯度β 太大时某些方向会以螺旋方式放大损失曲线先降后升甚至一步直接变成 NaN。我自己在二维二次型上试过A 取 [[1,0],[0,100]]β 0.9 没问题拉到 0.99 左右轨迹开始旋转收缩看起来还算正常一旦超过某个阈值轨迹从椭圆内侧向外螺旋损失很快飞掉。这个阈值可以直接由 β、步长 t 与特征值的组合算出。所以调试时如果碰到“加了动量反而崩了”先别怪算法多半是 β 和学习率的组合越过了谱边界。5. 把 19-24 讲串成一张网谱估计、预处理器与你的模型5.1 数据协方差谱与深度学习优化问题的病态性到了这六讲的后半段课程内容会重新拉回“真实数据”。深层网络的海森矩阵到底长什么样很多数值实验给出了大致结论特征值分布极其分散有一大批接近零的特征值也有一小部分明显的尖峰。这种结构与数据协方差矩阵的谱有直接联系。随机矩阵理论里有一个描述谱形状的经典公式当样本数和维度成固定比例时协方差矩阵的特征值会落在一个有界区间内并呈现某种密度分布形态。它意味着深度学习优化天然病态但一阶方法在实际任务里出奇地好用。原因之一是海森矩阵很大一部分谱对应“平坦方向”这些方向不需要极高精度随机梯度本身的噪声反而像一种隐式正则。另一个原因是小批量计算让每一步代价小很多同样的时间可以迭代更多步。有时“算得快”比“收敛快”更重要。5.2 预处理相似变换思想在优化中的落地病态条件数怎么治最直接的办法是换坐标系。如果能找到矩阵 M使 M⁻¹A 的特征值集中在 1 附近梯度下降的收敛率就会大幅改善这就是预处理器preconditioner的思想。从相似变换的角度看它没有改变问题的本质只是引入 M 的平方根做一次坐标变换把椭球等高线“掰”成圆。经典的 Jacobi 预处理只取对角元素更精细的不完全 Cholesky 预处理则近似模拟 A 的逆。深度学习里也有预处理形态BatchNorm 就是对网络内部激活做了一次近似白化。它让后续层面对的损失地形更接近球面这也是为什么加了 BatchNorm 后可以用更大的学习率。前面讲过的谱聚类、PCA、低秩近似本质上都是“换一个让数据谱更清晰的坐标系”和预处理是同一件事。5.3 回到自己的模型先测谱再选优化器如果这份 note3 只留下一句话我会写先了解你问题的谱再决定优化器。在实际项目中我不会一上来就盲选 Adam。小模型上可以用自动微分近似计算损失海森的最大特征值或者干脆把训练集抽一小块计算梯度协方差矩阵的谱得到“病态程度”的数量级。条件数接近 1 或只有几十普通 SGD 加适当动量完全够用条件数上千上万Adam 这类自适应方法更稳因为它隐式地对每个方向做了缩放条件数极大且还需要收敛证明再考虑真正的二阶方法或复杂预处理。这个选择顺序在 19-24 讲里被反复暗示是整份笔记最值得带走的方法论。6. 我整理 note3 期间的笔记方法、复现实验与踩坑记录6.1 用“递推-谱-收敛率”卡片记录每个算法我在整理这批内容时建立了一个固定模板每个算法一行公式下面接三块内容——递推关系、谱分析、最小实验。整理完以后六个 lecture 的核心内容变成几张卡片复习时扫一眼就能回忆起全貌。算法误差递推核心谱/收敛结论最小实验普通梯度e_{k1} (I - tA)e_kρ (κ-1)/(κ1)二维二次型锯齿路径动量法二阶差分增广块矩阵有效收敛率约 1/√κ同一问题上轨迹更平滑Nesterov外推点处计算梯度凸问题 O(1/k²)同一问题上收敛更快SGD梯度估计含噪声受梯度协方差谱影响调大噪声观察“跳出平坦区”每个算法配一个能独立运行的最小 python 实验比光看课本深刻得多。6.2 一个用 numpy 就能复现的二次型对照实验建议在 notebook 里做这样一组实验A 取 np.diag([1.0, 100.0])目标函数 f(x) 0.5·xᵀAx从 x0 (1.5, 0.5) 出发。分别用普通梯度、动量、Adam在同一总迭代数下记录损失曲线和参数轨迹。import numpy as np A np.diag([1.0, 100.0]) x np.array([1.5, 0.5]) lr 2.0 / (A[0, 0] A[1, 1]) # 理论最优步长 trace [x.copy()] for _ in range(50): grad A x x x - lr * grad trace.append(x.copy())你会看到普通梯度在山谷两侧来回反弹动量法明显平滑Adam 在前期更激进、后期更稳。然后把 A 改成 np.diag([1.0, 4.0])同一套代码再跑一遍会发现普通梯度的表现立刻变好。这就是条件数对收敛快慢的直观展示。整个实验不超过 40 行代码不需要 GPU两分钟就能跑完。6.3 实操中容易踩的坑最后记几个我踩过的坑。第一个曾经把“最速下降”当成“最快下降”在病态问题里浪费了大量时间。现在只要看到收敛很慢我第一反应是怀疑条件数而不是盲目加大迭代次数。第二个动量的 β 和学习率是一对联合参数不能只调其中一个。单独调大学习率很容易让增广矩阵的谱半径超过 1表现为损失先降后飞。调试时如果发现“加了动量反而崩”先检查 β 与学习率的组合是否越过稳定边界。第三个批量大小变化后要重新确认学习率。我踩过换 batch size 之后整个训练崩掉的坑。虽然有“线性缩放规则”这个经验公式但大批量时收敛本身会变差不一定直接按比例换学习率就完事。第四个做谱分析时别把左奇异向量和右奇异向量搞混。打印特征向量时经常看到方向对不上本质上是两套坐标系的问题。特别注意 SVD 的 V 和 U 分别对应行空间和列空间的方向。整理完这套 note3我最深的体会是优化器不是一堆孤立算法的堆叠离了矩阵谱很多结论都只是死记。如今我遇到训练收敛问题第一反应不再是“再加个 trick”而是做一次小小的谱侦察——大致摸清问题的病态程度再决定要不要上动量、要不要开大学习率、要不要换自适应方法。这种看问题的方式就是 18.065 最后这几讲留给我的最大收获。