一、BFGS算法
在“優化算法——擬牛頓法之BFGS算法”中,我們得到了BFGS算法的校正公式:

利用Sherman-Morrison公式可對上式進行變換,得到

令
,則得到:

二、BGFS算法存在的問題
在BFGS算法中。每次都要存儲近似Hesse矩陣
,在高維數據時,存儲
浪費非常多的存儲空間,而在實際的運算過程中。我們須要的是搜索方向。因此出現了L-BFGS算法。是對BFGS算法的一種改進算法。
在L-BFGS算法中。僅僅保存近期的
次迭代信息。以減少數據的存儲空間。
三、L-BFGS算法思路
令
。
,則BFGS算法中的
能夠表示為:

若在初始時,假定初始的矩陣
,則我們能夠得到:




若此時。僅僅保留近期的
步:

這樣在L-BFGS算法中。不再保存完整的
。而是存儲向量序列
和
。須要矩陣
時,使用向量序列
和
計算就能夠得到。而向量序列
和
也不是全部都要保存,僅僅要保存最新的
步向量就可以。
四、L-BFGS算法中的方向的計算方法

五、實驗仿真
lbfgs.py
#coding:UTF-8
from numpy import *
from function import *
def lbfgs(fun, gfun, x0):
result = []#保留終於的結果
maxk = 500#最大的迭代次數
rho = 0.55
sigma = 0.4
H0 = eye(shape(x0)[0])
#s和y用於保存近期m個,這里m取6
s = []
y = []
m = 6
k = 1
gk = mat(gfun(x0))#計算梯度
dk = -H0 * gk
while (k < maxk):
n = 0
mk = 0
gk = mat(gfun(x0))#計算梯度
while (n < 20):
newf = fun(x0 + rho ** n * dk)
oldf = fun(x0)
if (newf < oldf + sigma * (rho ** n) * (gk.T * dk)[0, 0]):
mk = n
break
n = n + 1
#LBFGS校正
x = x0 + rho ** mk * dk
#print x
#保留m個
if k > m:
s.pop(0)
y.pop(0)
#計算最新的
sk = x - x0
yk = gfun(x) - gk
s.append(sk)
y.append(yk)
#two-loop的過程
t = len(s)
qk = gfun(x)
a = []
for i in xrange(t):
alpha = (s[t - i - 1].T * qk) / (y[t - i - 1].T * s[t - i - 1])
qk = qk - alpha[0, 0] * y[t - i - 1]
a.append(alpha[0, 0])
r = H0 * qk
for i in xrange(t):
beta = (y[i].T * r) / (y[i].T * s[i])
r = r + s[i] * (a[t - i - 1] - beta[0, 0])
if (yk.T * sk > 0):
dk = -r
k = k + 1
x0 = x
result.append(fun(x0))
return result
function.py
#coding:UTF-8
'''
Created on 2015年5月19日
@author: zhaozhiyong
'''
from numpy import *
#fun
def fun(x):
return 100 * (x[0,0] ** 2 - x[1,0]) ** 2 + (x[0,0] - 1) ** 2
#gfun
def gfun(x):
result = zeros((2, 1))
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])
return result
testLBFGS.py
#coding:UTF-8 ''' Created on 2015年6月6日 @author: zhaozhiyong ''' from lbfgs import * import matplotlib.pyplot as plt x0 = mat([[-1.2], [1]]) result = lbfgs(fun, gfun, x0) print result n = len(result) ax = plt.figure().add_subplot(111) x = arange(0, n, 1) y = result ax.plot(x,y) plt.show()
實驗結果

