Introduction to Optimization(四): 拟牛顿法

本节介绍:

  • hessian matrix 近似
  • DFP算法
  • bfgs算法

hessian matrix 近似

牛顿法的基本思路是用二次函数来局部逼近目标函数 f 并解近似函数的极小点作为下一个迭代点,迭代公式

xxk+1=xxkαFF1(xxk)gk

但是牛顿法的缺陷是需要计算hessian矩阵,及其逆矩阵,但是实际上我们如果能保证 f(xk+1)<f(xk) , 就ok了,即我们想找到一个类似 F1 的矩阵 Hk ,使得迭代点
xxk+1=xxkαHHkgkf(xk+1)<f(xk)

xxk+1 出对 f(xk+1) 一阶泰勒展开
f(xxk+1)=f(xk)+gTk(xk+1xk)+o(||xk+1xk||)=f(xk)αgTkHkgk+o(||Hkgk||α)

为了保证 f(xk+1)<f(xk) ,必须有
Hk

拟牛顿法

拟牛顿法的迭代思路是

dkαkxk+1=Hkgk=argminf(xk+αdk)=xk+αdk

第二条件

对于正定矩阵 H0,H1,,Hn 当目标函数为 n 维二次型时,他们必须满足

Hk+1Δgi=Δxi,0ik

并且当它们满足以上条件的时候,可以证明(P135 定理 11.1) d0,d1,,di,,dn1 是Q共轭的,即将拟牛顿法用到 n 维二次型时只需要 n 步迭代即可到达最优解

由以上可以看到, Hk 并不是唯一确定的因此,我们需要找到一种方式让 Hk 满足条件并且容易计算
下面讲两种算法,分别是DFP和BFGS

DFP算法

  1. 选择初始点 x0,H0
  2. 计算 gk , 如果 ||gk||<ϵ 停止迭代
  3. 计算 dk=Hkgk
    计算 αk=argminα0f(xk+αdk)
    xk+1=xk+αkdk
    Δxk=αkdk
    Δgk=gk+1gk
    tmp=HkΔgk
    Hk+1=Hk+ΔxkΔxTkΔxTkΔgktmptmpTΔgTkHkΔgk

这里得证明这样构造的 Hk 满足两个条件

定理11.3
用DFP算法求解 二次型问题时,Hessian matrix Q=QT,,Hk+1Δgi=Δxi,0ik
因证明过程较为难写,故这里直接给出书上证明:
Introduction to Optimization(四): 拟牛顿法_第1张图片

定理11.4

假定 gk0, 只要有 Hk 正定 那么 Hk+1 正定

Introduction to Optimization(四): 拟牛顿法_第2张图片
Introduction to Optimization(四): 拟牛顿法_第3张图片

书上说,DFP 算法处理某些较大的非二次型问题是容易被’卡’ 住,所以后面有四个大牛提出了一种BFGS算法解决这一问题

BFGS

BFGS取自4个人的名字
图片来源于码农场
Introduction to Optimization(四): 拟牛顿法_第4张图片

前面提到的 Hk 满足的第二个条件即 Hk+1Δgi=Δxi,0ik 是根据 Δgi=QΔxi , 构造的 Q1 的近似矩阵 Hk , 同样,我们可以构造 Q 的近似矩阵 Bk+1 , 那么 Bk+1 满足

Δgi=Bk+1Δxi

利用互补的概念,应用DFP算法中的更新公式我们可以得到 Bk 的更新公式

Bk+1=Bk+ΔgkΔgTkΔgTkΔxk(BkΔxk)(BkΔxk)TΔxTkBkΔxk

因此 Hk+1=B1k+1

关于这个式子我们有如下引理

引理11.1
如果 A 非奇异, 列向量 u,vs.t,1+vTA1u0 , 那么其逆矩阵存在且

(A+uvT)1=A1(A1u)(vTA1)1+uTA1v

直接计算可证

因此应用两次引理,可得

HBFGSK+1=Hk+(1+ΔgTkHkΔgkΔgTkΔxk)ΔxkΔxTkΔxTkΔgkHkΔgkΔxTk+(HkΔgkΔxTk)TΔxTkΔgk

BFGS在实践中较为常用scipy.optimize 里面也有实现.以下是我的实现

代码实现

def dfp(fun, grad, x0, args=(), g_args=(), tol=1e-8, max_iter=5000):
    h0 = np.eye(len(x0))
    g_0 = grad(*((x0,) + g_args))
    alpha = lambda a, x, d: fun(*((x + a * d,) + args))
    for i in range(max_iter):
        if is_stop(g_0, np.zeros(g_0.shape), tol):
            break
        d = -h0.dot(g_0)
        alp = minimize_scalar(alpha, bounds=(0, 10000), args=(x0, d), method='brent', tol=1e-4)
        alp = alp.x
        x_next = x0 + alp * d
        delta_x = (alp * d).reshape((len(x0), 1))
        g_next = grad(*((x_next,) + g_args))
        delta_g = g_next - g_0
        delta_g = delta_g.reshape((delta_x.shape))
        tmp = h0.dot(delta_g)
        h0 = h0 + delta_x.dot(delta_x.T) / (delta_x.T.dot(delta_g)) - tmp.dot(tmp.T) / (delta_g.T.dot(tmp))
        x0 = x_next
        g_0 = g_next
    return OptimizeResult({'nit': i, 'x': x0, 'jac': g_0, 'fun': fun(*((x0,) + args))})


def bfgs(fun, grad, x0, args=(), g_args=(), tol=1e-8, max_iter=5000):
    h0 = np.eye(len(x0))
    g_0 = grad(*((x0,) + g_args))
    alpha = lambda a, x, d: fun(*((x + a * d,) + args))
    for i in range(max_iter):
        if is_stop(g_0, np.zeros(g_0.shape), tol):
            break
        d = -h0.dot(g_0)
        alp = minimize_scalar(alpha, bounds=(0, 10000), args=(x0, d), method='brent', tol=1e-4)
        alp = alp.x
        x_next = x0 + alp * d
        delta_x = (alp * d).reshape((len(x0), 1))
        g_next = grad(*((x_next,) + g_args))
        delta_g = g_next - g_0
        delta_g = delta_g.reshape((delta_x.shape))
        tmp = h0.dot(delta_g).dot(delta_x.T)
        tmp1 = (1+delta_g.T.dot(h0).dot(delta_g)/(delta_g.T.dot(delta_x)))*delta_x.dot(delta_x.T)/(delta_x.T.dot(delta_g))
        tmp2 = (tmp + tmp.T)/(delta_g.T.dot(delta_x))
        h0 = h0 + tmp1 - tmp2
        x0 = x_next
        g_0 = g_next
    return OptimizeResult({'nit': i, 'x': x0, 'jac': g_0, 'fun': fun(*((x0,) + args))})

DFP 与bfgs除了更新公式以外其他几乎完全一样

以下是在rosen 函数下的实验效果

bfgs result
 fun: 6.0875493993460361e-23
 jac: array([ -2.87637469e-10,   1.46505030e-10])
 nit: 17
   x: array([ 1.,  1.])
dfp result
 fun: 2.4549731009788525e-23
 jac: array([ -1.82560633e-10,   9.29922805e-11])
 nit: 17
   x: array([ 1.,  1.])

两次均优于共轭梯度算法.

实际使用

在实际使用中我们用的最多的还是SGD这样的用梯度来优化的算法,因为可以看到二阶项的一个重要的弊端就是空间复杂度太高,需要存贮二阶项,这对于 n 维的数据来说,需要 n2 的内存

本文链接http://blog.csdn.net/Dylan_Frank/article/details/78287680

你可能感兴趣的:(math)