4. 局部优化算法:阻尼最小二乘法、爬山法、共轭梯度法
局部优化,说白了就是在你已有的镜头结构上“微调”。你有一个初始设计,像差还有点大,需要让评价函数往下降。这时候,局部优化算法就上场了。
我刚开始做镜头设计时,总觉得算法是黑盒子,点一下优化按钮就完事。后来吃过几次亏才明白——选不对算法,优化就是在原地打转。今天咱们就把三种最常用的局部优化算法掰开揉碎讲清楚。
4.1 阻尼最小二乘法(DLS)
这是光学设计软件里最主力的算法。你想想看,优化本质上是在解一个超定方程组——变量比方程多,没有精确解,只能找“误差平方和最小”的那个解。
最小二乘法的思路很直接:把评价函数对变量求偏导,构造一个线性方程组,然后求解。但问题来了——如果步长太大,直接越过谷底;步长太小,又跑不动。
阻尼项就是干这个用的。它给步长加了一个“刹车”,防止优化过程震荡发散。
核心公式(简化版):
(AᵀA + μI)Δx = -Aᵀf
其中 μ 是阻尼因子,I 是单位矩阵。μ 大时,算法接近梯度下降,稳定但慢;μ 小时,接近高斯-牛顿法,快但容易发散。
我在项目中遇到过这样一个案例:一个手机镜头,初始结构 MTF 只有 0.3。直接用无阻尼的最小二乘法,优化到第 5 步就发散了,评价函数直接飞上天。换成阻尼最小二乘法,把 μ 初始值设成 0.1,每步迭代后检查评价函数——如果下降就减小 μ,如果上升就增大 μ。最后稳稳地收敛到了 MTF 0.6。
我的经验参数:
- 初始阻尼因子:0.01 ~ 0.1
- 阻尼调整策略:评价函数下降 → μ 乘以 0.7;上升 → μ 乘以 1.5
- 最大迭代步数:50 ~ 200 步,再多基本就是死循环了
4.2 爬山法
这个名字挺形象——你站在一个山坡上,想走到最低点,每次只朝下降最快的方向迈一步。说白了就是最速下降法。
优点很明显:实现简单,每一步只需要计算梯度方向,内存占用小。对于变量少(比如 5~10 个)的简单镜头,它跑得挺快。
缺点也很致命:收敛慢,尤其到了谷底附近,它会“之”字形震荡,半天落不下去。我见过一个投影镜头,用爬山法优化了 300 步还没收敛,换成 DLS 后 40 步就搞定了。
什么时候别用爬山法:
- 变量超过 15 个时——收敛速度会让你崩溃
- 评价函数有狭长谷底时——它会来回震荡,永远到不了最低点
- 需要高精度收敛时——爬山法在谷底附近的收敛精度远不如 DLS
不过,爬山法有一个特殊用途——全局探索的“扰动”阶段。我曾经在做一个变焦镜头时,先用全局搜索找到一个不错的初始点,然后用爬山法快速下降几步,看看周围有没有更低的谷。说白了,它更适合做“侦察兵”,不适合做“主力部队”。
4.3 共轭梯度法
这个算法是爬山法的“升级版”。它解决了最速下降法“之”字形震荡的问题。
核心思想:每次搜索方向不再是简单的负梯度方向,而是把当前梯度方向与上一次搜索方向做一个线性组合。这样就能保证每一步都朝着真正有效的方向走,不会来回折返。
公式长这样:
dₖ = -gₖ + βₖ · dₖ₋₁
其中 d 是搜索方向,g 是梯度,β 是组合系数。β 的计算方式有好几种,最常用的是 Fletcher-Reeves 公式和 Polak-Ribière 公式。
| 算法 | 收敛速度 | 内存占用 | 适用场景 |
|---|---|---|---|
| 阻尼最小二乘法 | 快(尤其谷底附近) | 高(需存储 Hessian 矩阵) | 变量多、精度要求高的镜头 |
| 爬山法 | 慢(谷底附近震荡) | 低(只需梯度) | 变量少、快速粗调 |
| 共轭梯度法 | 中等(比爬山法快 2~5 倍) | 低(只需两个向量) | 变量中等、内存受限的场景 |
我记得有一次做一个车载镜头,变量有 20 多个,但电脑内存只有 8GB。DLS 需要存储 20×20 的矩阵,算起来内存吃紧。换成共轭梯度法,内存占用只有 DLS 的十分之一,收敛速度虽然慢一点,但 80 步也收敛到了可接受的水平。
三种算法的选择建议:
- 变量 < 10:爬山法够用,简单直接
- 变量 10~30:共轭梯度法,平衡速度和内存
- 变量 > 30 或需要高精度:阻尼最小二乘法,一步到位
4.4 三种算法的关系与流程
这三种算法不是互斥的。实际项目中,我经常把它们组合使用。下面这张图展示了它们之间的关系和典型使用流程:
嗯,这里要注意——不要死磕一种算法。我个人的习惯是:先用爬山法跑 20 步,看看评价函数下降趋势。如果下降快,继续用;如果开始震荡了,马上切到共轭梯度法或者 DLS。
实战组合拳:
- 爬山法(20 步)→ 快速找到大致区域
- 共轭梯度法(30 步)→ 进一步下降,避免震荡
- 阻尼最小二乘法(50 步)→ 高精度收敛到谷底
这套组合我用了七八年,在几十个镜头项目里验证过,效果很稳定。
4.5 避坑指南
最后分享几个我踩过的坑:
- 阻尼因子设成固定值:我曾经在一个安防镜头项目里把 μ 固定成 0.01,结果优化到一半评价函数开始震荡。后来改成自适应调整,问题就解决了。
- 变量范围设得太宽:曲率半径从 -100 到 100,空气间隔从 0 到 50——这种设置会让算法在无效区域浪费大量步数。我建议初始范围控制在 ±20% 以内。
- 忽略边界约束:DLS 和共轭梯度法本身不带边界处理。如果你不手动加罚函数,优化出来的结果可能曲率半径是负的、空气间隔是负的——这种结构根本没法加工。
- 收敛判据设得太松:评价函数变化小于 1e-6 就停止?对于手机镜头这种高精度要求,这个判据太松了。我一般设到 1e-8 甚至 1e-10。
重要提醒:局部优化只能找到最近的局部极小点。如果你的初始结构离全局最优解很远,再好的局部优化算法也救不了你。这就是为什么下一类算法——全局优化——在某些场景下不可或缺。