拟牛顿法公式推导以及python代码实现(二)-BFGS家族

目录

  1. BFGS
    1.1BFGS公式推导
    1.2 python实现
  2. L-BFGS
    1.1 L-BFGS的完整推导

1.BFGS

1.1BFGS公式推导

BFGS是可以认为是由DFP算法推导出来的,上篇文章有详细的推导:(拟牛顿法公式推导以及python代码实现(一))

目前BFGS被证明是最有效的拟牛顿优化方法。它的思想是根据我们已知的两个拟牛顿条件:

HessBk+1sk=yk(1)
如该矩阵存在逆矩阵有:
HessHk+1yk=sk(2)
通过交换 HkBK,skyk 可以从DFP的关于 HK 的校正公式,得到关于 Bk 的校正公式,令 gk=f(xk) ,然后再将式中的参数全部换成用偏导 f(x) 可以表示的式子,就得到BFGS关于 Bk 校正公式了。说的那么抽象应该你也不明白,一步一步来推导试一下吧。

由上一篇文章,我们得到DFP的校正公式为:

Hk+1=Hk+sksTksTkykHkykyTkHkyTkHkyk(3)
由(1)得到关于 Bk 的BFGS校正公式:
Bk+1=Bk+ykyTkyTkskBksksTkBksTkBksk(4.1)
其实就是和(3)换了一下 sk,yk 的位置。

这个是BFGS的 BK Hessian矩阵形式的,要想得到它的Hessian逆阵的形式,需要多次使用Sherman-Morrison公式,推导太麻烦,在此不细讲。

现不加证明给出BFGS的 Hk 形式:

HBFGSk+1=(IskyTksTkyk)Hk(IyksTksTkyk)+sksTksTkyk(4.2)
该公式在接下来的L-BFSG的推导中将会用到。

1.2 python实现

由于 Bk+1 的公式较为简单,我们采用该校正公式进行实现有:
同样采用上一篇文章的优化问题 3.2,文章链接:拟牛顿法公式推导以及python代码实现(一)。

def bfgs(fun,gfun,hess,x0):
    #功能:用BFGS族算法求解无约束问题:min fun(x) 优化的问题请参考文章开头给出的链接
    #输入:x0是初始点,fun,gfun分别是目标函数和梯度,hess为Hessian矩阵
    #输出:x,val分别是近似最优点和最优解,k是迭代次数  
    maxk = 1e5
    rho = 0.55
    sigma = 0.4
    gama = 0.7
    epsilon = 1e-5
    k = 0
    n = np.shape(x0)[0]
    #海森矩阵可以初始化为单位矩阵
    Bk = np.eye(n) #np.linalg.inv(hess(x0)) #或者单位矩阵np.eye(n)

    while k < maxk:
        gk = gfun(x0)
        if np.linalg.norm(gk) < epsilon:
            break
        dk = -1.0*np.linalg.solve(Bk,gk)
        m = 0
        mk = 0
        while m < 20: # 用Wolfe条件搜索求步长
            gk1 = gfun(x0 + rho**m*dk)
            if fun(x0+rho**m*dk) < fun(x0)+sigma*rho**m*np.dot(gk,dk) and np.dot(gk1.T, dk) >=  gama*np.dot(gk.T,dk):
                mk = m
                break
            m += 1

        #BFGS校正
        x = x0 + rho**mk*dk
        print "第"+str(k)+"次的迭代结果为:"+str(x)
        sk = x - x0
        yk = gfun(x) - gk   

        if np.dot(sk,yk) > 0:    
            Bs = np.dot(Bk,sk)
            ys = np.dot(yk,sk)
            sBs = np.dot(np.dot(sk,Bk),sk) 

            Bk = Bk - 1.0*Bs.reshape((n,1))*Bs/sBs + 1.0*yk.reshape((n,1))*yk/ys

        k += 1
        x0 = x

    return x0,fun(x0),k#分别是最优点坐标,最优值,迭代次数 
x0 ,fun0 ,k = bfgs(fun,gfun,hess,np.array([3,3]))
print x0,fun0,k

使用Wolfe条件寻找步长 + BFGS的 Bk+1 形式校正,可得:

第0次的迭代结果为:[-7201.  1203.]
第1次的迭代结果为:[-3238.84711944  1221.61142361]
第2次的迭代结果为:[ -8.23623337e+04   1.30503639e+09]
第3次的迭代结果为:[ -3.36915508e+03   1.99855239e+07]
第4次的迭代结果为:[ -3.26209243e+03   3.56080380e+06]
-----
第3004次的迭代结果为:[ 1.00068614  1.00142718]
第3005次的迭代结果为:[ 0.99997941  0.99996238]
第3006次的迭代结果为:[ 0.99999746  0.99999526]
第3007次的迭代结果为:[ 1.00000001  1.00000001]
[ 1.00000001  1.00000001] 1.34694902629e-14 3008

迭代3008步才找到近似最优解
如果单独使用Armijo条件寻找步长的话:

第6298次的迭代结果为:[ 1.00031974  1.00067098]
第6299次的迭代结果为:[ 1.00001393  1.00002735]
第6300次的迭代结果为:[ 1.00000048  1.0000009 ]
第6301次的迭代结果为:[ 1.  1.]
[ 1.  1.] 3.15116026023e-16 6302

需要迭代6302步,但可以找到全局最优解[1. 1.]

2.L-BFGS

1.1 L-BFGS的完整推导

拟牛顿法如BFGS需要计算并存储Hessian矩阵,其空间复杂度为 n2 ,当n很大的时候,需要的内存量相当大,为了解决这个问题,L-BFGS就出来了。

L-BFGS的完整推导有空再写了

你可能感兴趣的:(最优化理论与优化算法,python,BFGS,最优化)