当围栏可碰可不碰
上一份指南解决的是约束必须严格成立的问题:在 g(x, y) = 0 的条件下极小化 f(x, y)。拉格朗日乘数告诉你:最优点落在 nabla f 与 nabla g 平行之处,因为沿着曲线 g = 0,已经没有任何被允许的方向能让 f 继续下降。但现实中大多数约束并非等式——它们是你不得越过的上限。预算说总成本 <= B,而非成本 = B。材料说应力 <= S。概率说 p >= 0。这些是不等式约束,写作 g(x) <= 0,它们以一种决定性的方式改变了几何:可行域如今是一块有边界的实心区域,而不再是一条细细的曲线。
有了实心的可行域,最优点可能落在两个本质不同的位置之一,而整套理论的关键就在于落在哪一个。要么最优点严严实实地落在区域内部,离每道围栏都很远——那么约束什么也没做,问题在局部就是一个普通的无约束优化,你只需像第一卷那样求解 nabla f = 0。要么最优点紧紧贴在某道围栏 g(x) = 0 上——那么该约束是起作用的(紧约束),其行为与上一份指南里的等式约束完全一样。难点在于:你通常事先并不知道自己处在哪一种情形;而 KKT 条件正是那套记账法,让代数替你做出判断。
乘数的符号如今承载了含义
假设极小值的确落在围栏 g = 0 上。和等式约束一样,我们仍需 nabla f = mu nabla g(mu 是某个乘数),因为在最优点处,没有任何可行方向能让 f 下降。但不等式是单边的,这种不对称性钉死了 mu 的符号——这是等式情形从不关心的。回忆:梯度 nabla g 指向 g 增大的方向,也就是越过围栏、朝向禁区 g > 0 的向外方向。要保持可行,你只能朝 nabla g 指向内侧或侧向之处迈步。要使 f 在这样一点没有可行的下降方向,nabla f 必须与 nabla g 指向同一个向外方向,这就迫使乘数非负:mu >= 0。
把这个符号条件作物理解读,它就不再是技术细节。乘数 mu 是一个影子价格:它度量的是,若你把围栏放松一丝(把 g <= 0 松到 g <= epsilon),f 的最优值会改善多少。mu 非负恰恰说出了直觉所要求的——放松一个紧约束只可能帮到你(或毫无影响),绝不会害你。如果你的代数在某个起作用的约束上算出 mu < 0,那它就不是一个可行的极小值:这意味着只要你迈下围栏、走进内部,f 反而会下降,所以真正的最优点在内部,而这个约束本应被判定为不起作用。符号正是抓出这一错误的检验。
互补松弛:那个巧妙的开关
现在来看那个把两种情形——内部或贴栏——熔合成一个整洁系统的巧招。我们为约束保留一个乘数 mu,并强加一条额外方程:mu g(x) = 0。这就是互补松弛,一个优雅的逻辑开关。乘积为零,当且仅当至少有一个因子为零,所以在任何一个解处,要么 mu = 0(乘数被关掉),要么 g = 0(约束起作用),或两者皆是。若最优点严格在内部,则 g < 0,于是该方程迫使 mu = 0,约束便从 nabla f = mu nabla g 中悄然消失,只剩下纯粹的 nabla f = 0。若最优点在围栏上,则 g = 0,mu 便可自由地取正值、去干它的活。一条方程,让解自己选择所处的状态。
把这些零件装到一起,你就得到了完整的 Karush-Kuhn-Tucker 条件——KKT 条件——用于在若干不等式约束 g_i(x) <= 0、以及可能存在的等式约束 h_j(x) = 0 下极小化 f。构造拉格朗日量 L = f + sum mu_i g_i + sum lambda_j h_j,与上一份指南如出一辙,只是有了两族乘数,并同时要求四件事:平稳性(对 x 有 nabla L = 0)、原始可行性(每个 g_i <= 0 且 h_j = 0)、对偶可行性(每个 mu_i >= 0——但等式乘数 lambda_j 的符号不受限制),以及互补松弛(每个 mu_i g_i = 0)。这两族乘数直接由上一份指南的多重约束机制推广而来。
KKT conditions (minimize f, constraints g_i(x) <= 0, h_j(x) = 0)
Lagrangian: L = f + sum_i mu_i g_i + sum_j lambda_j h_j
(1) stationarity nabla_x L = nabla f + sum mu_i nabla g_i + sum lambda_j nabla h_j = 0
(2) primal feasibility g_i(x) <= 0 and h_j(x) = 0 (stay legal)
(3) dual feasibility mu_i >= 0 (lambda_j free in sign)
(4) complementary slack mu_i * g_i(x) = 0 for every i (the switch)
Reading (4): g_i < 0 (slack) => mu_i = 0 (constraint idle)
mu_i > 0 => g_i = 0 (constraint active, on the fence)动手做:逐一枚举各情形
实践中,互补松弛把一个带不等式的问题变成了一次小小的有限搜索:对每个约束,你先猜它起作用还是不起作用,解出相应的等式系统,再用它没有假定的那些条件来核验这个猜测。来看一个干净的两变量例子——极小化 f(x, y) = (x - 2)^2 + (y - 2)^2,即到点 (2, 2) 的距离平方,约束为 x + y <= 2。无约束的极小值显然在 (2, 2),但那里 x + y = 4 > 2,不可行,所以围栏必然咬住。约束是 g = x + y - 2 <= 0;我们检验它起作用的情形。
- 先猜约束不起作用(mu = 0):则 nabla f = 0 给出 (x, y) = (2, 2)。检验可行性:x + y = 4,违反了 x + y <= 2。否决——内部情形不成立。
- 再猜约束起作用(g = 0):写下平稳性 nabla f + mu nabla g = 0。这里 nabla f = (2(x - 2), 2(y - 2))、nabla g = (1, 1),得到 2(x - 2) + mu = 0 与 2(y - 2) + mu = 0。
- 两式相减得 x = y;再由起作用的约束 x + y = 2,迫使 x = y = 1。于是候选点为 (1, 1)。
- 解出乘数:2(1 - 2) + mu = 0 给出 mu = 2。检验对偶可行性:mu = 2 >= 0。通过。于是 (1, 1) 配 mu = 2 满足每一条 KKT 条件,即为约束极小值。
图景与代数完美吻合:半平面 x + y <= 2 中离目标 (2, 2) 最近的点,正是从 (2, 2) 向边界直线所作垂线的垂足,即 (1, 1);而正乘数 mu = 2 记录着:把围栏向外推,会让你更靠近 (2, 2)——一次严格有益的放松,恰如一个非负影子价格应有的读法。当约束有好几个时,你会对「被宣布为起作用的约束」的每一个子集重复这套逐情形枚举,但每一情形内部的逻辑完全相同。
必要、充分,与诚实的边界
要精确说明 KKT 条件给出了什么,因为这里很容易夸大其词。一般而言,这些条件是必要而非充分的:在一个真正的局部极小值处它们成立(所以任何极小值都是 KKT 点),然而一个点可以满足全部四条而仍是极大值、鞍点,或仅仅是某个局部最优——这与第一卷无约束微积分里的 nabla f = 0 如出一辙,后者标出了临界点却不告诉你它的类型。KKT 把搜索缩小到一份有限的候选清单上;你仍须逐一检验,才能找出真正的极小值点。
有两点重要的告诫。第一,必要性本身需要一个温和的正则性假设——约束规范(最常见的一种是:在该点处,起作用约束的梯度线性无关)。没有它,即便在真正的极小值处乘数也可能不存在,于是 KKT 会悄悄漏掉它;这类退化的角点在实践中罕见,却真实存在。第二,也令人宽慰得多的是凸的情形:当 f 与每个 g_i 都是凸函数、且等式约束为线性时,KKT 条件就同时成为充分且必要的,任何满足它们的点都是全局极小值,而非仅仅局部。这正是凸问题中局部对全局最优的焦虑得以蒸发的结构性原因,也是工程师与机器学习从业者把凸性看得几乎高于一切的缘由。