拟牛顿法之BFGS算法

什么是拟牛顿法?

拟牛顿法是在牛顿法的基础上引入了Hessian矩阵的近似矩阵,避免每次迭代都计算Hessian矩阵的逆,它的收敛速度介于梯度下降法和牛顿法之间。拟牛顿法跟牛顿法一样,也是不能处理太大规模的数据,因为计算量和存储空间会开销很多。
拟牛顿法虽然每次迭代不像牛顿法那样保证是最优化的方向,但是近似矩阵始终是正定的,因此算法始终是朝着最优化的方向在搜索。具有全局收敛性和超线性收敛速度

BFGS公式推导

BFGS(Broyden,Fletcher,Goldfarb,Shanno四个人)算法是使用较多的一种拟牛顿方法,故称为BFGS校正。

x 写成x=(x1,x2,,xn)。对函数 f(x) x=xk+1 处进行泰勒展开到二阶:

f(x)=f(xk+1)+f(xk+1)(xxk+1)+12f′′(xk+1)(xxk+1)2+Rn(x)f(xk+1)+f(xk+1)(xxk+1)+12f′′(xk+1)(xxk+1)2

对上式求导并令其为0,由于 f(x) 中的 x 是一个向量,f(x) x 求导意味着对x向量中的每个值求偏导。即, f(x) x 的一阶导数为一个向量,对x的二阶导数为一个 nn 的矩阵
f(x)=(f(x)x1f(x)x2,,f(x)xn)f′′(x)=[2f(x)xixj]nn

求导后得:
f(x)=f(xk+1)+f′′(xk+1)(xxk+1)

即:
f(xk)=f(xk+1)+Gk+1(xkxk+1)

可以化简为:
f(xk+1)f(xk)=Gk+1(xkxk+1)

Bk+1Gk+1 ,则可得: Bk+1(xkxk+1)=f(xk+1)f(xk)
在BFGS校正方法中,假设:
Bk+1=Bk+Ek

BFGS校正公式的推导

Ek=αukuTk+βvkvTk ,其中 uk,vk 均为 n1 的向量。 yk=f(xk+1)f(xk),sk=xk+1xk .

那么 Bk+1(xkxk+1)=f(xk+1)f(xk)
可以化简为:

Bk+1sk=yk

Bk+1=Bk+Ek 代入上式得:
(Bk+Ek)sk=yk

Ek=αukuTk+βvkvTk 代入上式得:
(Bk+αukuTk+βvkvTk)sk=yk

即:

αuk(uTksk)+βvk(vTksk)=ykBksk

uTksk,vTksk 皆为实数, ykBksk n1 的向量,上式中,参数 α β 解的可能性有很多,我们取特殊的情况,假设 uk=rBksk,vk=θyk 。则:

Ek=αrBksTkBk+βθykyTk

代入上式:
α[(rBksk)Tsk](rBksk)+β[(θyk)Tsk](θyk)=ykBksk[αr2(sTkBksk)+1](Bksk)+[βθ2(yTksk)1](yk)=0

[αr2(sTkBksk)+1](Bksk)=0,βθ2(yTksk)1=0 ,则:
αr2=1sTkBkskβθ2=1yTksk

最终的BFGS校正公式为:
Bk+1=BkBksksTkBksTkBksk+ykyTkyTksk

BFGS校正的算法流程

Bk 对称正定, Bk+1 由上述的BFGS校正公式确定,那么 Bk+1 对称正定的充要条件是 yTksk>0

非精确的一维搜索(线搜索)准则:Armijo搜索准则,搜索准则的目的是为了帮助我们确定学习率,还有其他的一些准则,如Wolfe准则以及精确线搜索等。在利用Armijo搜索准则时并不是都满足上述的充要条件,此时可以对BFGS校正公式做些许改变:

Bk+1=Bk,BkBksksTkBksTkBksk+ykyTkyTksk,ifyTksk0ifyTksk>0

注:在李航写的那本《统计学习方法》中说是正定的,但是并没有说上述情况下会怎么样

算法

  1. 给定参数 δ(0,1),σ(0,0.5) ,初始化点 x0Rn ,终止误差 0ϵ1 ,初始化对称正定阵 B0 ,通常取为 G(xo) 或单位阵 In ;令 k=0
  2. 计算 gk=f(xk) ,若 gkϵ ,终止,输出 xk 作为近似极小点。
  3. 解线性方程组得解 dk : Bkd=gk .
  4. mk 是满足下列不等式的最小非负整数m:
    f(xk+δmdk)f(xk)+σδmgTkdk

    αk=δmk,xk+1=xk+αkdk .
  5. 由BFGS校正公式确定 Bk+1
  6. k=k+1 ,转向步骤“2”

求解具体优化问题

求解无约束优化问题:

minf(s)=100(x21x2)2+(x11)2,x=(x1,x2)TR2

#coding:UTF-8  
'''
Created on 2017年4月20日

@author: zhangdapeng
'''
from numpy import *    
import matplotlib.pyplot as plt
from numpy.matrixlib.defmatrix import mat
#fun  原始函数
def fun(x):  
    return 100 * (x[0,0] ** 2 - x[1,0]) ** 2 + (x[0,0] - 1) ** 2  

#对x1,x2求导后的函数  
def gfun(x):  
    result = zeros((2, 1))  
#     对x1求导
    result[0, 0] = 400 * x[0,0] * (x[0,0] ** 2 - x[1,0]) + 2 * (x[0,0] - 1)  
    result[1, 0] = -200 * (x[0,0] ** 2 - x[1,0])  #对x2求导
    return result  
def bfgs(fun, gfun, x0):  
    result = []  
    maxk = 500  
    delta = 0.55  
    sigma = 0.4  
    m = shape(x0)[0]  
    Bk = eye(m)  
    k = 0
    epsilon=1e-10
    while (k < maxk):  
        gk = mat(gfun(x0))#计算梯度 ,mat函数将数组转化为矩阵。
#         print(gk) 
#         print(linalg.norm(gk,1))
        #axis=0,沿着纵轴方向
        if linalg.norm(gk,1)<epsilon:
            break
        dk = mat(-linalg.solve(Bk, gk))  #解矩阵方程Bk*x=gk得到x
        m = 0  
        mk = 0  
        while (m < 20):  
            newf = fun(x0 + delta ** m * dk)  
            oldf = fun(x0)  
            if (newf < oldf + sigma * (delta ** m) * (gk.T * dk)[0,0]):  
                mk = m  
                break  
            m = m + 1  

        #BFGS校正  
        x = x0 + delta ** mk * dk  
        sk = x - x0  
        yk = gfun(x) - gk  
#         print(math.isnan(yk.T * sk))
        if (yk.T * sk > 0): 
            Bk = Bk - (Bk * sk * sk.T * Bk) / (sk.T * Bk * sk) + (yk * yk.T) / (yk.T * sk)  

        k = k + 1  
        x0 = x  
        result.append(fun(x0))  

    return result  

#初始化x0  
x0 = mat([[-1.2], [1]])  
result = bfgs(fun, gfun, x0)  
print("result:",result[-1])
n = len(result)  
ax = plt.figure().add_subplot(111)  
x = arange(0, n, 1)  
y = result  
ax.plot(x,y)  

plt.show()  

输出:

result: 2.68262011582e-28

输出图片:

这里写图片描述

http://blog.csdn.net/google19890102/article/details/45867789

http://blog.csdn.net/acdreamers/article/details/44664941
http://www.codelast.com/%E5%8E%9F%E5%88%9B%E7%94%A8%E4%BA%BA%E8%AF%9D%E8%A7%A3%E9%87%8A%E4%B8%8D%E7%B2%BE%E7%A1%AE%E7%BA%BF%E6%90%9C%E7%B4%A2%E4%B8%AD%E7%9A%84armijo-goldstein%E5%87%86%E5%88%99%E5%8F%8Awo/

  • 9
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值