3、无约束优化方法:梯度下降法原理、牛顿法与拟牛顿法、共轭梯度法、步长选择策略(Armijo准则)

无约束优化,说白了就是在一个没有围墙的院子里找最低点。你不需要考虑边界、约束、障碍物,只需要盯着目标函数本身往下走就行。这听起来简单,但实际做起来,坑多得很。

我个人习惯把无约束优化方法分成三类:一阶方法(只用梯度)、二阶方法(用梯度和海森矩阵)、以及介于两者之间的拟牛顿法。今天咱们就把这三类方法的核心逻辑、适用场景和避坑经验一次性讲透。

核心观点: 没有万能的优化器。梯度下降适合起步,牛顿法适合收尾,拟牛顿法是工程上的折中方案。
无约束优化方法体系 一阶方法 二阶方法 拟牛顿法 梯度下降法 随机梯度下降 (SGD) 牛顿法 阻尼牛顿法 BFGS L-BFGS 步长选择策略 固定步长 Armijo准则 💡 选择原则:问题规模大 → 一阶方法;精度要求高 → 二阶方法; 海森矩阵难求 → 拟牛顿法;步长自适应 → Armijo准则

3.1 梯度下降法:最朴素的下降方式

梯度下降法的思路非常直观:沿着当前点的负梯度方向走一步,然后重复。数学上就是:

x_{k+1} = x_k - α_k · ∇f(x_k)

其中 α_k 是步长,∇f(x_k) 是梯度。就这么简单。

但简单不等于好用。我在项目中遇到过一个问题:用固定步长的梯度下降法优化一个Rosenbrock函数,迭代了5000步还没收敛。后来换成自适应步长,200步就搞定了。你想想看,步长选大了会震荡,选小了又慢得像蜗牛。

经验之谈: 梯度下降法在远离最优解时效果不错,但接近最优解时收敛速度会明显变慢。这时候就该换方法了。

3.2 牛顿法与拟牛顿法

牛顿法的思路和梯度下降完全不同。它不光看梯度,还看曲率(海森矩阵)。说白了,它用二次曲面去逼近目标函数,然后一步跳到这个二次曲面的最低点。

更新公式:

x_{k+1} = x_k - [Hf(x_k)]⁻¹ · ∇f(x_k)

其中 Hf(x_k) 是海森矩阵。

牛顿法的收敛速度是二次的,比梯度下降快得多。但代价是什么?每次迭代都要计算海森矩阵并求逆,对于高维问题(比如1000维以上),这几乎不可行。

我记得有一次做图像配准的优化,目标函数有500个参数。用牛顿法,每次迭代光算海森矩阵就要花3秒,求逆又要2秒。迭代20步,一分钟就过去了。后来换成拟牛顿法,同样的精度,时间缩短到原来的十分之一。

拟牛顿法的核心思想是:不直接计算海森矩阵,而是用梯度差来近似它。最常用的两个变体是:

方法 核心思想 存储复杂度 适用场景
BFGS 用梯度差构造海森矩阵的近似 O(n²) 中等规模问题(n < 1000)
L-BFGS 只保存最近m步的梯度差 O(m·n) 大规模问题(n > 1000)
避坑指南: 我曾经在L-BFGS中把m(历史步数)设得太大,结果内存爆了。m一般取5-20就够了,别贪多。

3.3 共轭梯度法

共轭梯度法是个很有意思的方法。它介于梯度下降和牛顿法之间,既不需要计算海森矩阵,又比梯度下降收敛快。

它的核心思想是:每次迭代的搜索方向都和前一次的方向共轭(关于海森矩阵正交)。这样就能保证在n步内收敛到二次函数的最优解。

更新公式:

d_k = -∇f(x_k) + β_k · d_{k-1}
x_{k+1} = x_k + α_k · d_k

其中 β_k 的计算方式有多种,最常用的是Fletcher-Reeves公式:

β_k = ||∇f(x_k)||² / ||∇f(x_{k-1})||²

共轭梯度法在求解大规模线性方程组和神经网络训练中都有广泛应用。我个人习惯在内存受限的场景下优先考虑它。

3.4 步长选择策略:Armijo准则

步长怎么选?固定步长肯定不行。那怎么办?Armijo准则给出了一个简单而有效的自适应方案。

Armijo准则的核心思想是:步长要足够大,让目标函数有显著下降;但又不能太大,防止跳过最优解。

数学表达:

f(x_k + α · d_k) ≤ f(x_k) + c₁ · α · ∇f(x_k)ᵀ · d_k

其中 c₁ 是一个常数,通常取 0.0001 到 0.1 之间。这个不等式保证了函数值有足够的下降。

实际实现时,通常采用回溯法:

  1. 初始化 α = 1(或一个较大的值)
  2. 检查Armijo条件是否满足
  3. 如果不满足,α = α · ρ(ρ通常取0.5-0.8)
  4. 重复直到条件满足

代码实现:

def armijo_backtracking(f, grad_f, x, d, c1=0.1, rho=0.5, alpha_init=1.0):
    alpha = alpha_init
    f_x = f(x)
    grad_dot_d = np.dot(grad_f(x), d)
    
    while f(x + alpha * d) > f_x + c1 * alpha * grad_dot_d:
        alpha *= rho
        
    return alpha
实用建议: c₁ 不要取太大,否则步长会变得非常小,收敛变慢。我一般取 0.1 或 0.01。ρ 取 0.5 是个不错的起点。

Armijo准则的好处是:它不需要计算海森矩阵,只需要计算函数值和梯度。对于大规模问题,这非常实用。

嗯,这里要注意一点:Armijo准则只保证充分下降,不保证步长最优。它找到的是一个"足够好"的步长,而不是"最好"的步长。但在工程实践中,"足够好"往往就够了。

我曾经在一个项目中,用固定步长的梯度下降法优化一个非凸函数,结果在鞍点附近来回震荡,死活下不去。后来加上Armijo回溯,步长自动调整,很快就穿过了鞍点区域。这就是自适应步长的威力。

总结: 无约束优化的核心就三件事——选方向、定步长、判断收敛。方向决定了你能不能到,步长决定了你多久能到,收敛判断决定了你什么时候停。