ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

《最优化理论与方法》导读:从经典算法到深度学习优化器

《最优化理论与方法》导读:从经典算法到深度学习优化器 最近总有学弟学妹跑来问我同一个问题搞机器学习和算法优化到底需不需要系统啃最优化理论每次我都把袁亚湘院士和孙文瑜教授合著的《最优化理论与方法》扔给他们。这本书在国内最优化学科里算是宗师级教材网上PDF流传很广但我不打算在这篇文章里贴下载链接原因有两个一是盗版电子书页边页脚经常缺批注、公式渲染错乱体验极差二是这本书真的值得你花钱买正版反复翻放书架上是能传家的那种。我更想认认真真聊清楚一件事——这本经典的《最优化理论与方法》到底在教什么为什么它里面的每一个算法今天都还在用以及一个普通人应该用什么顺序把它真正读懂、用起来。如果你是非数学专业出身或者刚入行做算法工程师、运筹优化工程师这篇文章就是一次全程白话的导读。我会把最核心的无约束优化、约束优化、对偶理论一条条拆开讲再顺手把书里的经典算法和深度学习里那堆SGD、Adam、动量法串起来。读完你会发现现在大模型训练里的很多花活底层逻辑几十年前就写在这本书里了。1. 这本书到底讲了什么一张最优化地图1.1 教材定位与内容骨架《最优化理论与方法》是科学出版社出的研究生教材也是国内高校数学、计算机、管理科学、控制工程相关专业最常用的一本优化教材。它的定位不是通俗科普而是带完整理论证明的教科书。全书大致分成几块最优化问题的基础知识凸集、凸函数、矩阵分析、无约束最优化方法最速下降、牛顿法、共轭梯度、拟牛顿、约束最优化理论拉格朗日乘子、KKT条件、罚函数法、可行方向法以及线性规划、二次规划和最小二乘问题。很多初学者拿到书会被厚度和公式密度吓住但如果你把它看成一幅地图就豁然开朗了。整本书其实只回答三个问题怎么描述一个优化问题怎么判断一个解好不好怎么高效找这个解。每一个算法章节都在解决其中一个子问题。袁亚湘和孙文瑜两位老师的写法非常学院派每一个定理都给了完整证明但恰恰是这种严谨让你后面少踩很多坑——随便找博客学习你很难搞清楚为什么某个算法在特定条件下会失效而这本教材把这些边界条件全部摊开了。1.2 为什么今天还要读经典教材有人说这书太老了没有讲深度学习优化器跟不上时代。这是最大的误解。SGD、Adam这些算法在原理解层面全都能在经典优化理论里找到对应位置。深度学习优化器不过是把通用的最速下降法、拟牛顿思想放到高维非凸问题的特殊场景里再加了工程上的变体处理。比如Adam的动量和自适应学习率核心思路和共轭方向法里的共轭性、拟牛顿法里的尺度校正一脉相承。没有经典理论打底你调学习率就是纯玄学遇到loss震荡、训练不收敛只能干瞪眼。另一个重要原因是这本书训练的是建模直觉。现实中你遇到的具体问题几乎都不是现成的教科书题可能是物流路径优化可能是推荐系统的排序学习可能是投资组合配置。你首先得把业务问题抽象成数学规划模型判断它是凸问题还是非凸问题决定用经典优化器还是启发式算法。这些判断能力只能在对理论体系有整体认知之后才能建立。2. 无约束优化从最速下降到拟牛顿的核心逻辑2.1 最速下降法原理、公式与之字形陷阱无约束优化是全书的核心起点形式就是一层皮 min f(x)没有任何约束条件。最直观的思路就是从某个初始点出发沿着让函数值下降最快的方向走。这个方向就是负梯度方向所以最速下降法的迭代格式写成x_{k1} x_k - α_k ∇f(x_k)其中α_k是步长。书里会花大量篇幅讲怎么确定这个步长精确线搜索、Armijo回溯、Wolfe条件。很多初学者觉得步长就是拍脑袋选个0.01其实不然。步长选大了迭代震荡甚至发散选小了收敛慢得像蜗牛。Armijo条件就是一个非常实用的工程判断准则只要新的函数值相比当前值下降得足够多就走这一步否则把步长按比例缩小。这比固定步长强太多因为它在每一步都在做自适应调整。最速下降法最经典的失败案例是触碰之字形问题。为了方便理解拿一个二维二次函数 f(x,y) x² 10y² 来说。这个函数在x方向上比较平坦在y方向上非常陡峭条件数最大特征值和最小特征值之比是10。用最速下降法从某个离原点较远的点出发每一步都严格垂直于上一步的方向结果就是走一步锯齿形、再走一步锯齿形路径歪歪扭扭迭代几百次才逼近最优解。如果条件数变成100甚至1000那基本就是在原地绕圈。这也是为什么固定步长的标准梯度下降在实际高维问题里很容易让人怀疑人生。这个现象背后有数学原因步长选取精确线搜索时相邻两次迭代方向必然正交。一个很病态的函数轮廓是拉长的椭圆最速下降方向在椭圆长短轴之间来回横跳收敛速率被条件数卡死。书里给出了线性的收敛速率公式告诉你它慢在哪、为什么慢。理解了这一点你才算真正入门优化。2.2 牛顿法与拟牛顿法引入二阶信息既然一阶信息不够那就看二阶。牛顿法的思路是对目标函数在x_k处做二阶泰勒展开直接找展开模型的极小点作为下一个迭代点。方向是d_k -[∇²f(x_k)]⁻¹ ∇f(x_k)也就是用赫森矩阵的逆矩阵对梯度方向做一个线性变换把椭圆等高线圆化步长等效取1。对正定二次函数一次迭代就精准到达最小值点这就是所谓的二阶收敛性速度远快于普通梯度法。但牛顿法有两处硬伤。首先是每步都要计算并存储n×n的赫森矩阵求逆n是变量维度高维问题里这个开销根本无法接受。其次是赫森矩阵可能不可逆甚至不正定数值上非常不稳定。针对这些问题书里引出了拟牛顿法家族——不精确计算赫森矩阵而是通过迭代中梯度信息的变化去逼近它的逆或者它的本身。最常用的BFGS公式长这样B_{k1} B_k (y_k y_kᵀ)/(y_kᵀ s_k) - (B_k s_k s_kᵀ B_k)/(s_kᵀ B_k s_k)这里s_k是迭代点变化量y_k是梯度变化量。这个公式在我眼里堪称艺术品——只靠相邻两步的梯度和位置变化就不断修正出对曲率的估计。另一个常考的DFP公式是BFGS的变体用在逆矩阵上。我在实际工程里凡是中小规模非线性优化问题首选就是L-BFGS因为它节省内存、收敛速度快又有拟牛顿的曲率校正能力非常稳。这本书对拟牛顿法的剖析之深至今没有几本中文教材能超越。3. 约束优化拉格朗日对偶与KKT3.1 等式约束与拉格朗日乘子法现实世界的问题几乎都带约束。工厂生产要受原料库存限制货物运输要受车辆载重限制投资组合要受资金总量限制。这类问题在数学上一般写成min f(x) s.t. g_i(x) 0, i 1, ..., m解决等式约束优化最经典的工具是拉格朗日乘子法。构造拉格朗日函数 L(x, λ) f(x) Σ λ_i g_i(x)然后把所有变量都当成自由变量求梯度为零。这里λ就是拉格朗日乘子它有很直观的经济学含义——在最优解处λ_i告诉你如果约束g_i放宽一个单位最优目标值会改善多少这就是所谓的影子价格。书里对这个部分有两个绝佳的证明一个是必要性证明严格推导为什么在约束流形上的最优解必须满足拉格朗日函数梯度为零另一个是对偶性的引入说明原始问题和对偶问题之间的关系。我当年第一次读到这里时醍醐灌顶原来SVM里那个求对偶问题、把优化目标换成α系数全部都是拉格朗日对偶具体化的过程。3.2 不等式约束、KKT条件与凸规划不等式约束的处理比等式约束复杂得多因为它牵扯到这个约束到底有没有起作用的判断。KKT条件本质上就是把起作用约束的拉格朗日乘子强制设非负同时对每个不等式约束增加一个互补松弛条件λ_i g_i(x) 0。KKT条件的核心有四条梯度为零平稳性、原问题可行、对偶变量可行、互补松弛。对凸优化问题来说KKT条件是全局最优解的充分必要条件这个性质有多值钱值钱到整个凸优化理论都建立在上面。你在机器学习的资料里经常看到凸优化问题满足KKT条件即可求解说的就是这件事。袁亚湘教材对约束最优化的另一大贡献是罚函数法。外点罚函数法直接把约束以惩罚项形式加到目标函数里违反约束越多罚得越狠内点罚函数法则构造障碍函数让迭代点始终停留在可行域内部。这两种方法本质上是把约束优化化成一系列无约束优化来解。但这里有个实操经验罚参数不要一上来就取特别大的值否则目标函数会变得很病态数值求解器容易崩。正确做法是逐渐增大罚参数上一轮的解作为下一轮初始点这个策略叫路径跟踪。4. 从经典理论到现代深度学习优化器4.1 为什么从批梯度下降到SGD聊完了书里的经典算法必须把它们和现在深度学习里的优化器连起来看。经典最速下降法在今天对应的是批量梯度下降每一步都需要计算全部样本的梯度然后沿负梯度更新。问题是深度学习的损失函数是几百万样本上的求和形式一次全量梯度算下来又慢又费内存完全不可用。于是有了随机梯度下降SGD每次只抽一个或一小批样本估计梯度用它代替全局梯度去更新。这样做带来的梯度估计是有噪声的但工程上传奇之处在于噪声反而帮了忙——它给了模型逃离鞍点和局部极小值的机会。这个思想在书里其实也有雏形任何对真实梯度的近似只要误差可控迭代仍然有收敛性质。SGD相当于用一个方差较大的梯度估计量配合退火的学习率在非凸问题里表现得非常好。我从这本书中得到一个实操启发不要迷信SGD就是慢。标配热身的做法是先用SGD配合学习率衰减跑一遍观察loss曲线的形态再决定要不要切自适应优化器。SGD加上动量在简单任务上常常比Adam泛化效果更好这个大家实测普遍认可。4.2 动量、自适应学习率与Adam讲到动量法本质就是给梯度方向加一个加速度记忆。更新公式是v_t γ v_{t-1} η∇f(θ_{t-1}) θ_t θ_{t-1} - v_t引入速度项之后参数更新不再对每步梯度做剧烈反应而是顺着历史方向的惯性继续走。这正好抵消了最速下降法的锯齿效应。如果你做过优化实验一定见过SGD在有条件数问题的目标上做大幅往复震荡加一个动量项之后路径会迅速变得平滑并加速收敛。自适应学习率方法的动机更直接。梯度下降对每个参数用同一个步长但不同参数在不同方向的曲率差异很大有的参数应该大步走有的应该小步走。Adagrad用历史梯度平方和的平方根来逐参数缩放学习率RMSProp改为指数移动平均Adam则综合了一阶矩和二阶矩的估计公式如下m_t β₁ m_{t-1} (1-β₁) g_t v_t β₂ v_{t-1} (1-β₂) g_t² θ_t θ_{t-1} - η * m̂_t / (√(v̂_t) ε)这里m̂_t和v̂_t是偏差修正项。对照拟牛顿法的思想看Adam其实很有意思拟牛顿法在每次迭代里用曲率信息做坐标变换Adam则是用梯度二阶矩的估计逐维度调整步长。一个是精确的矩阵变换一个是统计意义的对角缩放。两者都在做同一件事校正目标函数不同方向尺度差异带来的收敛困难。这本书的理论能帮你理解这些现代变体的前世今生。5. 手写优化器从零实现梯度下降与牛顿法5.1 实验代码与结果对比理论光看没有用一定要动手实验。我最推荐的做法拿书里最简单的两个算法用Python手写一遍喂给一个病态的二次函数亲眼看看收敛行为的差异。这儿给出一份可以直接运行的代码。import numpy as np # 目标函数 f(x,y) x^2 100*y^2, 条件数 100 A np.array([[2., 0.], [0., 200.]]) def f(x): return 0.5 * x.T A x 3.0 def grad_f(x): return A x # Armijo回溯线搜索 def backtrack(x, d, f, grad_f, alpha01.0, rho0.5, c0.1): alpha alpha0 g grad_f(x) while f(x alpha * d) f(x) c * alpha * g.T d: alpha * rho return alpha # 最速下降法 def steepest_descent(x0, max_iter1000, tol1e-8): x x0.copy() history [x.copy()] for i in range(max_iter): g grad_f(x) if np.linalg.norm(g) tol: break d -g alpha backtrack(x, d, f, grad_f) x x alpha * d history.append(x.copy()) return x, len(history) - 1 # 牛顿法 def newton_method(x0, max_iter20, tol1e-8): x x0.copy() for i in range(max_iter): g grad_f(x) if np.linalg.norm(g) tol: break H A d -np.linalg.solve(H, g) x x d return x, i 1 x0 np.array([5.0, 1.0]) x_sd, it_sd steepest_descent(x0) x_nt, it_nt newton_method(x0) print(f最速下降法: 迭代{it_sd}次, 解{x_sd}) print(f牛顿法: 迭代{it_nt}次, 解{x_nt})我实际跑出来的结果是最速下降法用了几百次Armijo回溯一步步逼近原点迭代轨迹明显呈锯齿状牛顿法只要1次就一步到位因为对正定二次函数牛顿法的模型就是原函数本身一步直接到达精确最优解。差别就是这么震撼。5.2 实验结论与参数选择心得这个实验给你三个实操层面的启发。第一固定学习率的梯度下降在病态问题上极不可靠线搜索和动量是廉价却高效的修复方式。第二二阶信息是收敛速度的加速器但代价是高维矩阵求逆成本因此真实工程环境里优先考虑L-BFGS这类拟牛顿法做中小规模优化。第三在深度学习的训练里偶尔把模型权重全部展平当成一个大规模无约束问题来看用一阶优化器更新本质就是在做最速下降的变体你调学习率策略时应该想象你在选一条下山路径而不是在调一个神秘魔法数字。我自己做这类实验时会额外做一组对照只改变条件数从10到1000看最速下降法迭代次数的变化。肉眼可见地迭代次数按条件数的比例剧烈增加。这个现象在书里列过公式但你亲手跑出来之后对病态问题的恐惧感会转化为一种直觉以后看到某个模型训练慢你会下意识去查特征尺度而不是盲目调高学习率。6. 学习路线、避坑指南与排查速查6.1 怎么读这本书从开门到吃透我的建议是第一遍不要追求看懂所有定理证明。先把第一章到第三章通读重点建立算法长什么样、为什么用梯度方向、为什么牛顿法快的粗框架所有证明可以先跳过。然后动手跑一遍上面那种小实验让理论照进现实。接着再回头细读第四章拟牛顿法和第六章约束最优化的KKT条件这部分的证明是全书精华值得花几周慢慢推。读之前最好复习三样东西高等数学里的多元 Taylor 展开、线性代数里的矩阵分解和特征值、以及一点点凸分析基础。你不需要先修一门完整的凸优化课但要认得半正定矩阵和范数。这本书默认读者有这些基础所以如果你的线代底子不够建议先花一周快速过一遍线性代数的二次型、特征值分解、奇异值分解。关于正版获取我真心建议去京东、当当或者出版社官方渠道买纸质版顺便支持一下科研工作者的劳动成果。好的教材像一位严格的老师你砸过钱的、做过笔记的书你会愿意反复翻这是免费电子版永远比不了的。6.2 常见问题与排查技巧我在带项目、答疑时经常遇到一些典型问题整理成速查表拿走直接用。现象可能原因排查与对策目标函数值上升不下降导数方向算错步长太大打印梯度范数改用Armijo回溯检查符号是否取了正梯度迭代卡住不收敛loss呈锯齿目标函数条件数大使用特征归一化加入动量考虑自适应学习率优化器牛顿法报矩阵奇异赫森矩阵不可逆或者不正定加正则项λI换BFGS拟牛顿法用信赖域约束步长有约束问题一直违反约束罚函数参数太小增大罚因子并用路径跟踪改内点法直接求解KKT系统深度学习训练发散学习率过大或数据尺度不统一调低学习率做梯度裁剪先跑一个极小模型验证损失计算另外有一个很多人不知道的细节用SciPy里的minimize做无约束优化时method选BFGS还是L-BFGS-B差别很大。问题变量少于几百个时BFGS更准大到上万维时L-BFGS-B更省内存但要多留出一部分迭代次数让曲率信息慢慢积累。这就是书里讲的拟牛顿法在实践中的落地经验。还有一条避坑心得不要在非凸问题上随便宣称找到了全局最优。书里给出全局最优的理论保证只适用于凸规划。我自己做过一个结构优化项目目标函数是非凸的随手拿梯度下降跑到一个解就交差后来换了好几个随机初始点结果每个都不同才知道掉进了局部最优。正确做法是全局搜索和局部精修相结合先拉丁超立方采样或者粒子群搜一个大范围再让梯度法去精修。我个人绕不开的一个体会是真正把这本书读透的标志不是你记得多少个公式而是遇到一个新问题能快速判断它属于哪个类别该用哪一把工具。有一次我给一个朋友排查推荐系统排序模型训练不收敛最后定位到是特征做embedding后的尺度差异太大本质上就是条件数问题。别人觉得我在玄学调参我知道我在优化理论里找到了答案——这个感觉很棒。最后再分享一个小技巧每次读完一章用思维导图把这章涉及的算法、适用前提、优缺点、对比对象画出来。学完无约束优化后画一张学完约束优化再画一张两张图拼起来你手里就有了一整套优化兵器谱。以后碰到任何优化问题先翻兵器谱再决定出哪把刀。这套方法我自己用了很多年不管是发论文还是做实际项目都非常管用。
返回列表