36 分钟
AI 数学精要

凸性、鞍点与拉格朗日:优化为什么难

用凸性判断能不能保证拿到全局最优,搞清高维场景里真正的障碍是鞍点,再用拉格朗日乘子手算约束优化问题

  • 能判别简单函数的凸性,能说清凸优化为什么有全局最优保证
  • 区分局部最小、全局最小、高原与鞍点,用 Hessian 特征值判类型
  • 解释为什么高维非凸问题里鞍点远多于局部极小
  • 手算一个带等式约束的最小化问题,用拉格朗日乘子法。讲清楚它和正则化的关系。

梯度为零的地方不一定是答案——优化的难度由「曲面形状」决定

上一节讲了沿梯度走的方法,但走到梯度为零的位置,就一定是最低点吗?这节讲优化理论最核心的三个问题:什么样的曲面能保证你走到的就是全局最优(凸性)、梯度为零却不是最优时会遇到什么(鞍点)、参数被施加约束时怎么求极值(拉格朗日乘子)。这三个点能解释「为什么神经网络训练这么难,又为什么实践中居然能训成」。

3.1 凸函数:弦始终在曲线之上

凸函数的定义很直接:函数 f 是凸函数,当任意两点连线上的点都不低于函数本身,也就是对 0≤t≤1 有 f(t·x+(1−t)·y) ≤ t·f(x)+(1−t)·f(y)。几何上就是「碗形」:任意两点拉一条弦,弦在曲面上方。一元光滑函数可以用二阶导判别:f″≥0 处处成立就是凸函数。比如 f=x² 的 f″=2>0,是凸的;f=−x² 的 f″=−2<0,是凹的,也就是倒扣的碗;f=x³ 的 f″=6x,x<0 时为负、x>0 时为正,所以它不是全局凸。

凸性为什么珍贵?因为在凸函数上,任何局部最小值都必然是全局最小值,且梯度下降类算法有收敛到全局最优的理论保证。你不会走进一个假的低谷再也出不来。逻辑回归、线性回归、支持向量机都属于凸优化,所以它们「怎么初始化都能收敛到同一个最优解」;而神经网络因为叠加了非线性、参数共享,损失关于参数高度非凸,这是深度学习理论与实践的分水岭。

凸性还有强弱之分。若在凸之外还满足 f(y)≥f(x)+∇f(x)·(y−x)+(μ/2)·‖y−x‖²(曲率有正的下界 μ),称强凸,典型如加了 L2 的最小二乘、逻辑回归。收敛速率因此可量化:一般光滑凸问题梯度下降的误差按 O(1/t) 衰减(t 步后与 1/t 同阶),强凸时按线性速率 O(ρᵗ) 指数收缩。这些速率是分析非凸神经网络时的对照基线——后者没有这种保证,只能靠实验观测。

选择题

下列关于凸函数的陈述,正确的是?

3.2 临界点的三种面孔:极小、极大、鞍点

梯度为零(∇f=0)的点统称驻点(临界点),但它有三种完全不同的面孔。局部极小:四周都比它高;局部极大:四周都比它低;鞍点:沿某些方向是极小、沿另一些方向却是极大,形如马鞍中央或山口。仅凭梯度为零无法区分,必须看 Hessian 的特征值:全部为正(正定)→局部极小;全部为负(负定)→局部极大;有正有负(不定)→鞍点。

来,咱们手算鞍点 f(x,y)=x²−y²。先看原点的梯度:∇f=[2x,−2y]=[0,0],梯度确实是零。再算Hessian矩阵:[[2,0],[0,−2]],特征值是 +2 和 −2,一正一负。沿x方向,原点是谷底——x²是向上开口的;沿y方向,原点反而是坡顶——−y²向下开口。所以原点是鞍点,不是极值点。要是只盯着x方向看,你会误判「到最低了」,换y方向看,其实还能一直往下降。这就是只看单一方向会被骗的原因。

示例代码(可运行)
直觉

为什么高维空间里鞍点远多于局部极小

Hessian 的 n 个特征值里,要成为局部极小必须「全部为正」,成为局部极大必须「全部为负」,只要正负混合就是鞍点。假设每个特征值正或负的概率各半,n 个全正的概率只有 (1/2)ⁿ,n=100 时约为 10⁻³⁰,混合正负的概率压倒性地接近 1。高维参数空间维度成百上千,驻点几乎都是鞍点,真正的局部极小反而稀少。这直接改了优化研究的焦点:神经网络训练的主要障碍不是陷入局部极小,是怎么逃离大片鞍点与平缓高原。动量、噪声 SGD 之所以有效,部分原因正是它们能沿负曲率方向「滑出」鞍点。

3.3 高原、峡谷与病态条件:比极值更常见的麻烦

现实损失曲面上,训练卡住往往不是因为到了极值,而是地形本身难走。高原(plateau)是一大片梯度近乎为零的平缓区,模型会长时间「看起来没进步」后突然下降;狭长峡谷中,梯度在陡壁间来回横跳、却沿谷底前进极慢,这正是需要动量与自适应学习率的原因(l4 展开);条件数很大(Hessian 最大与最小特征值悬殊)时,不同方向需要的步长差很多,单一学习率顾此失彼。

填空题填写空白处的代码
f(x,y)=x²−y² 在原点 # 梯度 ∇f=[2x,]=[0,0](填 -2*y) # Hessian 特征值为 +2 和 (填 -2) # 一正一负 -> 原点是(填:鞍点)

3.4 拉格朗日乘子:带约束时让梯度「平行」

前面讲的都是无约束条件下找最小值,现实里经常有约束:资源有限、权重受限、概率和为 1。等式约束问题的写法是 min f(x),满足 g(x)=0。拉格朗日的思路是,把约束乘上系数 λ 再加到目标函数里:ℒ=f+λ·g,然后对所有变量(包括 λ)求偏导,令偏导为零。几何上的直觉很好懂:在约束边界上取到 f 的极值时,f 的梯度必须和约束的梯度平行——不然沿约束边界还能继续往下降。λ 就是这个平行关系的比例,也叫影子价格,意思是约束放松一单位,最优值能改善多少。

手算:最小化 f=x²+y²(到原点距离平方),约束 x+y=2(写成 g=x+y−2=0)。ℒ=x²+y²+λ(x+y−2)。求偏导:∂ℒ/∂x=2x+λ=0→x=−λ/2;∂ℒ/∂y=2y+λ=0→y=−λ/2,故 x=y;代入约束 x+y=2 得 x=y=1,最优 f=1²+1²=2。几何上就是直线 x+y=2 上离原点最近的点 (1,1),距离 √2,与直觉完全吻合。

示例代码(可运行)
预测输出
min x²+y² s.t. x+y=4,用同样方法(对称性 x=y)求最优点的 x 等于多少?

3.5 正则化就是「软约束」,不等式约束靠 KKT

L2 正则可以换个拉格朗日的角度理解:「在权重平方和不超过预算 C 的约束下最小化损失」和「最小化损失+λ·Σw²」是同一个问题的两种表述。前者是硬约束,后者是用 λ 调节的软约束,λ 越大等价于预算越紧。这个视角把「正则化防过拟合」和「约束优化」串起来了。更一般的不等式约束(g≤0)由 KKT 条件刻画,是拉格朗日的推广,支持向量机等模型的解就建立在 KKT 上。这里先把「约束→乘子→正则」这条主线理清楚就行。

不等式约束先看个最小例:min x² 满足 x≥1。无约束最小在 x=0,但它违反约束,最优被「推」到边界 x=1,此时乘子非零、约束恰好取等,这叫互补松弛——约束不起作用时乘子为 0,起作用时解落在边界。KKT 共四条:梯度稳定条件、原始约束可行、对偶可行、互补松弛同时成立。拉格朗日对偶还能给出原问题最优值的下界,是 SVM 与约束深度学习的理论工具,现阶段掌握「等式用拉格朗日、不等式看 KKT、正则即软约束」即可。

局部极小只在邻域内最低;凸函数中它就是全局最小。Hessian 全部特征值为正(正定)。

配对题把曲面/条件对到它的判据或后果
找 Bug梯度为零只说明走到驻点,非凸网络里可能是鞍点或高原,不能据此判定全局最优。
# 训练到某点梯度范数≈0,立刻宣布「找到全局最优」并停止 if grad_norm < 1e-8: return 'global minimum' # 对非凸网络,仅凭 ∇f≈0 就下结论
🐍神经网络非凸,为什么实践中还能训好

行内共识很明确:超大网络的损失景观里,优质局部极小值不仅数量多,彼此的损失值还很接近。SGD 自带的噪声、加上小 batch 训练,反而能帮你避开差劲的鞍点;过参数化的存在,也让抵达低损失解的路径变多了。 所以工程上根本不追求全局最优,找「泛化良好的低损失盆地」就行,配合多种子、学习率调度、动量这些手段来提稳定性。

⚠️别把「收敛」等同于「梯度严格为零」

实际训练几乎不会精确到达 ∇f=0,通常在一个区域内小幅波动就视为收敛;反过来梯度很小也可能只是高原或鞍点。判断训练是否到位,看验证损失趋势、有没有到平台期,别盯着梯度是否归零。

ℹ️凸优化仍是值得学的「干净基线」

别觉得神经网络是非凸的,凸优化就没用。很多子问题本身还是凸的——注意力后的归一化、最优输运、对比学习的部分目标、SVM,全是。凸优化里的对偶、强凸收敛速率、条件数这些概念,就是你分析非凸算法时能用的通用语言,也是下界参照。

💡判断卡在什么地形的快速实验

损失长期不降时:给参数加一次小随机扰动。若能继续下降,多半困在鞍点/高原;若立刻弹回,可能是局部极小;不同方向损失变化差异巨大,是病态峡谷,应换 Adam 或加梯度裁剪。

选择题

高维神经网络训练中,梯度为零的点绝大多数是什么?为什么?

本节小结

一条因果链:凸函数(f″≥0、弦在曲线上)保证局部最优即全局最优,神经网络非凸故无此保证 → ∇f=0 只是驻点,靠 Hessian 特征值正定/负定/不定区分极小、极大、鞍点 → 高维下全正概率极低,鞍点与高原才是主要障碍 → 等式约束用拉格朗日 ℒ=f+λg、在梯度平行处取极值(手算 x²+y² s.t. x+y=2 得 (1,1))→ L2 正则是权重预算的软约束、不等式约束由 KKT 推广。

资深工程师加餐

底层原理 · 大厂视角 · 工程经验,点卡片展开

一条样本是一个特征向量,一批样本堆成矩阵,神经网络一层的变换本质就是矩阵乘法加激活。换基/特征值分解相当于找数据的主要方向(PCA 降维),GPU 之所以适合深度学习,正是因为它能大规模并行做矩阵运算。把「向量=对象、矩阵=变换」建立起直觉,后面公式就不再抽象。