带过一个实习生他问我一个问题参数估计和凸优化到底是两门课还是同一门课我当时没有正面回答因为这个问题问得比表面上要深。参数估计解决的是“根据数据把模型参数定下来”凸优化解决的是“在约束下找最优解”听起来各管各的但在实际工作中你几乎不可能只做其中一个而不碰另一个。可以说不懂凸优化的参数估计是盲人摸象不懂参数估计的凸优化是屠龙之术。这篇文章我想把这两个主题放在一条线上讲清楚参数估计怎样把问题写成优化形式凸优化怎样保证我们能有效地求出答案。适合正在学机器学习的同学、写论文需要推导的研究生以及那些被 Python 库封装的 solver 搞到怀疑人生的工程朋友。我会尽量从原理讲到实操再讲一些只有上手之后才懂的细节。1. 参数估计与凸优化是怎么被绑在一起的1.1 估计问题的本质是“找一个不坏的答案”先想一个问题给你一堆身高数据让你估计这批人的平均身高。大部分人第一反应是求样本均值。但为什么是均值更深层的答案是如果你假设身高服从高斯分布那么样本均值恰好就是让数据出现概率最大的那个参数。这就是最大似然估计MLE在所有候选参数里挑一个让当前观测数据“看起来最合理”的参数。把这个问题一般化假设数据服从分布 (p(x|\theta))观测到数据集 (D{x_1,...,x_N})似然函数为[ L(\theta)\prod_{i1}^{N} p(x_i|\theta) ]由于连乘容易数值下溢习惯上取负对数变成最小化问题[ \hat{\theta}{\mathrm{MLE}} \arg\min{\theta} \left[ -\sum_{i1}^{N} \log p(x_i|\theta) \right] ]这里的“负对数似然”就是目标函数模型参数就是决策变量。到这里估计问题已经变成了优化问题。你不再需要直接解方程只需要求一个目标函数的最小值。所以第一条关键认知参数估计的产出不是“公式”而是“目标函数”。公式只有在对某些特定分布如高斯分布、伯努利分布下才存在闭式解而目标函数可以借助数值方法求解。这就是凸优化介入的起点。1.2 为什么负对数似然往往是凸的很多人学到最大似然时会有一个疑问凭什么负对数似然是凸的万一估计出来的目标函数坑坑洼洼那优化不就白做了吗关键在于你选择的概率分布。在统计学里有一类非常重要的分布族叫指数族分布形式是[ p(x|\theta) h(x)\exp\left{\eta(\theta)^T T(x) - A(\theta)\right} ]其中 (\eta(\theta)) 是自然参数(T(x)) 是充分统计量(A(\theta)) 是配分函数的对数。高斯分布、伯努利分布、泊松分布、伽马分布都属于指数族。对这个形式取负对数似然目标函数会包含一项 (-A(\theta))而指数族分布恰好满足 (A(\theta)) 是凸函数所以负对数似然整体是凸的。这意味着只要你的模型假设在指数族范围内MLE对应的优化问题天然就是凸优化问题。这就是为什么线性回归高斯噪声假设、逻辑回归伯努利假设的目标函数都是凸的这不是巧合而是概率分布的性质带来的。提示如果你把模型换成混合高斯、深度神经网络等非指数族模型目标函数就不再保证凸性后面我会讲到这些怎么办。1.3 把估计写成优化问题的标准套路综合上面两点从参数估计问题到凸优化问题的转换基本可以总结成一套固定流程提出概率模型给定一组数据定义一个你认为能解释数据的概率分布。写出似然把所有样本的概率密度乘起来。取负对数得到目标函数乘法变加法数值上更稳定。添加正则项如果参数维度高或数据量少在目标函数后面加 (L_1) 或 (L_2) 惩罚。交给求解器把目标函数、梯度和约束条件交给求解器得到最优参数。这套流程做多了以后你会形成肌肉记忆。看到一个新的模型第一反应不是“能不能写出公式”而是“目标函数长什么样、梯度能不能解析表达、是不是凸问题”。这种思维转换是从学生思维到从业者思维的第一步。2. 凸优化不是“凸函数求最小”一句话那么简单2.1 凸集、凸函数、凸问题三件套凸优化的定义其实有严格的三层结构很多人只记住了中间一层导致实际操作时判断失误。第一层是凸集。一个集合 (C) 是凸的如果任意两点之间的连线都在集合内。你可以想象一个被压扁的塑料瓶它表面向内凹陷的部分就不是凸集因为连接凹陷两端点的线会跑到形体外面。欧氏空间里的超平面、半空间、多面体都是凸集。第二层是凸函数。函数 (f) 是凸的如果对定义域内任意两点 (x_1, x_2) 和任意 (t\in[0,1])有[ f(tx_1 (1-t)x_2) \leq t f(x_1) (1-t)f(x_2) ]这个不等式的直觉是函数图像上的割线总是在函数图像上方。如果函数二阶可导且定义域是凸集那么判断凸性更简单看海森矩阵是否半正定。一维情况下就是看二阶导数是否恒大于等于零。第三层是凸问题。标准的凸优化问题要求目标函数是凸函数等式约束必须是仿射的不等式约束必须是凸函数且满足“小于等于零”。写成标准形式是[ \begin{aligned} \min_{x} \quad f(x) \ \text{s.t.} \quad g_i(x) \le 0, \quad i1,...,m \ h_j(x) 0, \quad j1,...,p \end{aligned} ]很多人会问如果我的约束不满足这个结构怎么办答案是很多实际问题可以改写成这种结构这就是“建模的艺术”。比如把非光滑的 (L_1) 范数约束改写成一堆线性不等式约束。2.2 为什么凸问题里局部最优就是全局最优这是凸优化最核心、也最被人低估的性质。对于一般的非凸问题局部最优解可能只是一个小山包里的坑外面还有更深的谷。但对凸问题目标函数就像一个大碗不管你怎么走朝下坡方向走一步就是在朝碗底走一步而且碗底是唯一的在严格凸情况下。数学上可以证明凸问题中任何局部极小点都是全局极小点。这个性质的实际意义非常巨大。它意味着找到的解一定是全局最优不需要反复尝试不同初始点。证明一个问题是凸的等于给你的算法上了一道保险。在工业级求解器中复杂度有多项式级上界不像非凸问题那样可能指数爆炸。我在实际项目里经常遇到这种情况工程师写完代码发现优化不收敛第一反应是换优化器第二步是调学习率最后才去检查目标函数的凸性。其实顺序应该反过来先判断凸性再用合适的求解器。凸性判断错了后面所有调参都是在浪费电。2.3 用岭回归做一个手把手的凸性判定练习举个例子。岭回归的目标函数是[ J(\beta) |y - X\beta|_2^2 \lambda |\beta|_2^2 ]第一项是残差平方和展开后是[ |y - X\beta|^2 \beta^T X^T X \beta - 2y^T X \beta y^T y ]这个函数关于 (\beta) 的二次项系数是 (X^T X)它总是半正定的所以残差平方和是凸函数。第二项是 (\lambda \beta^T \beta)海森矩阵是 (2\lambda I)当 (\lambda0) 时严格正定。两个凸函数相加仍然是凸函数因此整个目标函数都严格凸。结论是岭回归的最优解唯一可以放心用梯度下降或者直接求闭式解。这个练习虽然简单但它展示的“拆解每项函数、分别判定凸性、再合成”的方法适用于几乎所有机器学习模型。3. 无约束问题求解梯度下降与其“亲戚”的真实差异3.1 最速梯度下降的行为模式当你确认一个优化问题是凸的接下来的问题是怎么求解。无约束情况下梯度下降是最广为人知的方法[ \theta_{k1} \theta_k - \eta_k \nabla f(\theta_k) ]其中 (\eta_k) 是步长学习率。理论上如果步长选择合适且函数满足利普希茨平滑条件梯度下降可以收敛到全局最优。但收敛速度和你关心的精度之间有一个容易被忽略的工程问题固定步长很难挑。步长太大目标函数震荡甚至发散。步长太小收敛极慢像蚂蚁爬楼。实践中我习惯用回溯线搜索backtracking line search来自适应确定步长先设一个较大初始步长如果目标函数没有充分下降就按比例缩小步长。这个办法简单、稳能省下大量人工调参时间。如果函数条件数很大——形象地说等高线呈苹果形而非圆形——普通梯度下降会呈现“之”字形前进收敛慢得让人怀疑人生。这时需要换更好的算法。3.2 动量、Nesterov、Adam它们分别解决了什么动量Momentum方法引入了速度变量[ \begin{aligned} v_{k1} \gamma v_k \eta \nabla f(\theta_k) \ \theta_{k1} \theta_k - v_{k1} \end{aligned} ]它的直觉是如果相邻几步梯度方向一致就加速前进如果方向频繁改变就自动减速。在高条件数问题上动量能大幅抑制“之”字形振荡。Nesterov 加速进一步做了改进先“看一眼”下一步的位置再计算梯度相当于多了一个校正项。理论上它能把凸光滑问题的收敛阶从 (O(1/k)) 提升到 (O(1/k^2))这是一种非常优雅的“引路式”优化思路。Adam 则结合了动量思想与二阶矩自适应它不仅记录梯度的指数滑动平均一阶矩还记录梯度平方的指数滑动平均二阶矩然后对每个坐标分别修正步长。这让 Adam 在深度学习中表现优异但对凸问题它不一定比 L-BFGS 这类二阶方法更稳。我的建议是标准凸光滑问题且特征维度不高优先考虑 L-BFGS 或牛顿法。深度学习、大规模稀疏问题、目标非光滑考虑 SGD/Adam。需要在线上持续更新模型选 SGD 或 Adam因为它们对非稳定环境适应更好。3.3 工程上几个不写进教材的细节特征标准化。哪怕你的目标函数凸性完美如果各特征量纲差距巨大等高线会被拉得极扁梯度下降会走得很痛苦。把所有特征标准化到均值 0、方差 1 之后绝大多数求解器都能表现更好。初始化不要小看。虽然凸问题不依赖初始点收敛到正确解但初始点选择会影响前几百次迭代的损失下降速度。一个常用的启发式是用零向量初始化线性模型参数用随机初始化配合交叉验证做神经网络参数。监控梯度范数而不是只看损失。我习惯每轮迭代后看 (|\nabla f(\theta_k)|_2)当它低于一个阈值比如 (10^{-5})时认为达到收敛。只看损失曲线容易被“平台期”欺骗——平台期损失下降很慢但梯度可能还有很多信息等待挖掘。下表是一个我常用的算法选择参考场景推荐算法理由小样本、光滑凸目标L-BFGS收敛快、内存消耗低中等规模、非光滑目标次梯度法/近端梯度处理不可导项超大规模、特征稀疏SGD/Adam单次迭代开销小需要高精度解牛顿法二次收敛深度模型Adam 或 SGD momentum对复杂曲面适应好4. 二阶方法牛顿法与拟牛顿法到底赢在哪4.1 牛顿法的核心直觉牛顿法不是“更快的梯度下降”它背后的逻辑完全不同。梯度下降只用了函数的一阶泰勒展开牛顿法则用了二阶泰勒展开[ f(\theta) \approx f(\theta_k) \nabla f(\theta_k)^T(\theta-\theta_k) \frac{1}{2}(\theta-\theta_k)^T H(\theta_k)(\theta-\theta_k) ]对这个二次近似求极小点得到迭代公式[ \theta_{k1} \theta_k - H(\theta_k)^{-1} \nabla f(\theta_k) ]其中 (H(\theta_k)) 是目标函数的海森矩阵。直觉上牛顿法不仅知道当前斜坡有多陡还知道斜坡的弯曲程度因此能以更短的路径直达谷底。在目标函数是二次凸函数的情况下牛顿法一步就能收敛。但牛顿法的代价也很明显要计算并求逆海森矩阵参数维度为 (n) 时一次迭代的复杂度是 (O(n^3))。当模型有几千个参数这还勉强能忍当参数达到几十万、上百万几乎不可能直接计算海森矩阵。4.2 L-BFGS 如何在“算不动海森矩阵”时发挥作用拟牛顿法Quasi-Newton走的是另一条路不直接计算海森矩阵而是在迭代过程中利用相邻两次的梯度差逐步逼近真实海森矩阵的逆。最早提出的 DFP 和 BFGS 方法都是这个思路。BFGS 迭代需要维护一个 (n\times n) 的矩阵存储开销依然是 (O(n^2))。L-BFGSLimited-memory BFGS则更进一步它只保存最近 (m) 次迭代的变量差和梯度差利用这些历史信息隐式地近似海森矩阵的逆存储开销降为 (O(mn))通常取 (m10\sim30)。这是逻辑回归、支持向量机等模型的标准选择。我在实践中用 L-BFGS 跑了大量带 (L_2) 正则的逻辑回归训练数据几十万条、特征维度几千列收敛稳定且很快。相比之下用 Adam 反而需要反复调学习率收敛精度也不如 L-BFGS。4.3 一阶与二阶方法选择的经验法则一个常见误区是“无脑用 Adam 就万事大吉”。Adam 在处理深度网络时确实很好用但对凸优化问题尤其当你需要高精度解的时候L-BFGS 和截断牛顿法往往更合适。原因很简单一阶方法需要大量迭代才能把误差降到极小量级而二阶方法能借助曲率信息更快逼近最优解。选择时可以按这三个维度判断参数维度几千以下直接用 L-BFGS几千到几百万近端梯度或 SGD几百万以上考虑分布式优化。精度要求科学计算类的参数估计往往需要高精度二阶方法更有优势机器学习模型通常不需要高精度推荐一阶方法即可。目标光滑性目标函数存在不可导项如 (L_1) 正则标准的牛顿法无法直接使用需要加上近端映射。提示如果你的问题允许先用小规模数据跑一次 L-BFGS得到一个参考解再在大规模数据上用一阶方法逼近。这样即使最终使用一阶方法你也能知道“最优解大概在哪”。5. 带约束的凸优化拉格朗日对偶与正则项的另一层含义5.1 从“加惩罚”到“加约束”的等价转换带约束的优化问题是凸优化中更一般的形式。比如一个带 (L_1) 约束的参数估计问题可以写成[ \min_{\theta} \sum_{i1}^{N} \ell(\theta; x_i) \quad \text{s.t.} \quad |\theta|_1 \le \tau ]这个约束刻画了参数向量的稀疏性。而常见的 (L_1) 正则化形式[ \min_{\theta} \sum_{i1}^{N} \ell(\theta; x_i) \lambda |\theta|_1 ]在某种意义下和上述约束问题是等价的对每个 (\tau)都存在一个 (\lambda) 使得两个问题的最优解相同。区别在于约束形式更直观地体现了“参数范围限制”而正则化形式更容易数值求解。理解这种转换非常有用。比如当你需要控制模型的某些行为时可以明确地想我是限制参数的范数还是限制预测结果的变化范围这两者对应的约束表达式完全不同。5.2 拉格朗日函数与 KKT 条件到底在说什么为约束优化定义拉格朗日函数[ L(x, \lambda, \nu) f(x) \sum_{i1}^{m} \lambda_i g_i(x) \sum_{j1}^{p} \nu_j h_j(x) ]其中 (\lambda_i \ge 0) 是不等式约束对应的对偶变量(\nu_j) 是等式约束对应的对偶变量。KKT 条件是在凸问题下最优点必须满足的必要且在一定约束规格下充分的条件包括梯度为零条件拉格朗日函数关于 (x) 的梯度为零原始可行性所有约束都成立对偶可行性(\lambda_i \ge 0)互补松弛性(\lambda_i g_i(x)0)。互补松弛条件最有直觉价值它说明在最优解处不等式约束要么“卡紧”了(g_i(x)0)对应 (\lambda_i 0)要么“完全没有起到限制作用”(\lambda_i0)。这就像一个拥挤场地里真正把人群挡住的栅栏才受力没有接触到的栅栏不受力。在很多参数估计问题中数据约束并不会在最优解处全部卡紧所以对应的大部分对偶变量为 0。这种稀疏性可以让求解算法集中精力在“有效约束”上大幅提升效率。5.3 一个经典例子软间隔支持向量机SVM 的目标是找一个超平面让两类数据间隔最大化。软间隔 SVM 的原始问题可以写成[ \begin{aligned} \min_{w,b,\xi} \quad \frac{1}{2} |w|^2 C \sum_{i1}^{N} \xi_i \ \text{s.t.} \quad y_i(w^T x_i b) \ge 1 - \xi_i, \quad \xi_i \ge 0 \end{aligned} ]通过拉格朗日对偶可以转化为对偶问题[ \max_{\alpha} \quad \sum_{i1}^{N} \alpha_i - \frac{1}{2} \sum_{i,j} \alpha_i \alpha_j y_i y_j x_i^T x_j ][ \text{s.t.} \quad 0 \le \alpha_i \le C, \quad \sum_{i1}^{N} \alpha_i y_i 0 ]对偶问题中只出现了 (x_i^T x_j) 形式的内积这为核技巧打开了大门只要把内积替换成核函数线性 SVM 就变成了非线性分类器。从参数估计角度看对偶变量 (\alpha_i) 可以理解为每个样本在分隔超平面附近的重要程度非零 (\alpha_i) 对应的样本就是支持向量。5.4 为什么有时候反而要解对偶问题一个直觉问题是原始问题是凸的直接解不就行了吗为什么还要转对偶约束复杂时对偶问题的约束往往更简单。比如上面 SVM 的对偶约束只是一组“盒子约束”加一个线性等式。对偶变量提供了敏感度信息。(\lambda_i) 的数值大小告诉你第 (i) 个约束对最优值的影响程度这在参数估计中可以用来识别“哪些样本是关键样本”。对偶问题有时可以分块求解适合大规模分布式计算。但也要记住弱对偶总会成立强对偶原始最优值等于对偶最优值并不自动成立。对凸问题在 Slater 条件下强对偶成立对非凸问题对偶间隙可能很大用时需小心。6. 真实世界不那么凸非凸参数估计的破局思路6.1 非凸问题的典型来源不是所有参数估计问题都天然是凸的。非凸性的来源有很多深度神经网络几乎都是非凸模型目标函数有大量局部极小、鞍点和平坦区域。高斯混合模型用 EM 算法求解但 EM 只能保证收敛到局部极值。低秩矩阵分解、非负矩阵分解、主题模型等也都有非凸性。在贝叶斯框架下计算后验分布时优化和采样同样面临非凸难题。这些问题的共同特点是你无法保证找到全局最优只能退而求其次找到“足够好的局部最优”。这听起来让人沮丧但实际工程中如果模型表达能力足够强且有足够的正则化局部最优解往往也足够好。6.2 实操中最有效的几个非凸优化策略按投入产出比排序我推荐以下策略多起始点法。用多组不同随机初始化值跑多次优化选损失最小的解。这是最简单、收益最稳定的做法。注意要设置固定随机种子保证结果可复现。退火或课程式训练。先在一个平滑的、更容易优化的代理目标上训练再逐步过渡到原始目标。深度学习中的学习率预热、渐进增强图像分辨率本质都是这个思路。贪心逐层优化。对某些结构已知的非凸问题如深度网络、矩阵分解可以逐层或逐分量求解每步只优化一部分参数。混合高斯模型里的“先聚类再精调”也属于这种。用凸松弛提供初始点。比如用核范数松弛替代低秩约束得到凸问题后求出一个解再把它作为原始非凸问题的初始值。这样的初始点通常比其他随机初始点更接近全局最优。6.3 一个被低估的步骤先画损失地形图非凸问题里最容易被忽视的操作是可视化损失曲面和参数路径。许多深度学习框架都有 embedding projector 之类的工具可以把高维参数映射到二维空间。在调参前先做一个低维度简化版的损失曲面图能直观告诉你问题是“平坦大碗”还是“锯齿迷宫”。这项工作比盲目调学习率高效得多。另一个经验是每一步优化实验都记录下来超参、随机种子、初始值、最终损失、收敛时间。达芬奇说“简单是终极的复杂”但在优化调参里记录和复现才是终极的可靠。6.4 看起来非凸但其实是凸的情况有些问题表面上复杂但通过变量替换可以变成凸问题。一个典型例子是几何规划原问题约束形式非凸但通过对变量取对数可以转化成凸问题。另一个例子是相位恢复phase retrieval问题在某些测量矩阵条件下可以使用凸松弛得到全局最优。遇到非凸问题我的习惯是先问三个问题能不能换一种参数化方式让新的变量空间里是凸的能不能把约束稍作修改转成一个已知的凸问题能不能把问题拆成几个子问题每个子问题单独是凸的如果三个回答都是否定的才去接受非凸优化的现实并采用上面提到的策略。写在最后的一点体会参数估计与凸优化的关系我最想用一句概括参数估计给了你“要什么”凸优化给了你“怎么拿”。前者是你面对数据时的建模假设后者是你求解时的可靠阶梯。二者缺一不可。如果让我给出一条最实用的入门路线那就是先用岭回归和逻辑回归这两个标准模型把“MLE目标函数—凸性验证—L-BFGS/近端梯度求解—结果解释”整套流程走通再去碰深度学习和复杂概率模型。这个过程不需要读完整本凸优化教科书但足以让你建立最重要的直觉——看到目标函数第一眼先判断能不能保底找到全局最优再决定投入多少计算资源。我在实际项目中踩过最大的坑就是一上来就用 Adam 去训一个逻辑回归结果不仅收敛慢还要反复调学习率。后来换成 L-BFGS几分钟就收敛了精确度也比 Adam 高一个量级。那次之后我只要看到“凸函数 中小规模数据”第一反应永远是二阶方法。希望这篇内容能帮你把两个看似分开的领域打通。真正的精通不来自背下所有公式而是来自面对一个实际问题时知道它落在哪个地图区域然后掏出正确的工具。
