拟牛顿法
一、牛顿法
1.1 基本介绍
牛顿法属于利用一阶和二阶导数的无约束目标最优化方法。基本思想是,在每一次迭代中,以牛顿方向为搜索方向进行更新。牛顿法对目标的可导性更严格,要求二阶可导,有Hesse矩阵求逆的计算复杂的缺点。XGBoost本质上就是利用牛顿法进行优化的。
1.2 基本原理
现在推导牛顿法。
假设无约束最优化问题是
minxf(x)
对于一维 x 的情况,可以将 f(x(t+1)) 在 x(t) 附近用二阶泰勒展开近似:
f(x(t+1))=f(x(t))+f′(x(t))Δx+12f″(x(t))Δx2
然后用泰勒展开的极值点近似 f(x) 的极值点:
∂f(x(t+1))∂x(t+1)=f′(x(t))+f″(x(t))Δx=0
因此
Δx=x(t+1)−x(t)=−f′(x(t))f″(x(t))=−gtht
于是得到迭代公式,g和h分别是目标在当前x上的一阶和二阶导
x(t+1)=x(t)−gtht
推广到x是多维向量的情况,gt 仍然是向量,而 Ht 是Hesse矩阵
H=[∂2f∂xi∂xj]
以二维x=(x1,x2)为例:
H=⎡⎣⎢⎢⎢∂2f∂x21∂2f∂x2x1∂2f∂x1x2∂2f∂x22⎤⎦⎥⎥⎥
参数更新方程推广为:
x(t+1)=x(t)−H−1tgt
可见,每一次迭代的更新方向都是当前点的牛顿方向,步长固定为1。每一次都需要计算一阶导数g以及Hesse矩阵的逆矩阵,对于高维特征而言,求逆矩阵的计算量巨大且耗时。
1.3 阻尼牛顿法
从上面的推导中看出,牛顿方向 −H−1g 能使得更新后函数处于极值点,但是它不一定是极小点,也就是说牛顿方向可能是下降方向,也可能是上升方向,以至于当初始点远离极小点时,牛顿法有可能不收敛。因此提出阻尼牛顿法,在牛顿法的基础上,每次迭代除了计算更新方向(牛顿方向),还要对最优步长做一维搜索。
算法步骤
(1)给定给初始点 x(0),允许误差 ϵ
(2)计算点 x(t) 处梯度gt和Hesse矩阵H,若|gt|<ϵ则停止迭代
(3)计算点 x(t) 处的牛顿方向作为搜索方向:
d(t)=−H−1tgt
(4)从点 x(t) 出发,沿着牛顿方向 d(t) 做一维搜索,获得最优步长:λt=argminλf(x(t)+λ⋅d(t))
(5)更新参数 x(t+1)=x(t)+λt⋅d(t)
二、拟牛顿法
2.1 提出的初衷
牛顿法中的Hesse矩阵H在稠密时求逆计算量大,也有可能没有逆(Hesse矩阵非正定)。拟牛顿法提出,用不含二阶导数的矩阵 Ut 替代牛顿法中的 H−1t,然后沿搜索方向 −Utgt 做一维搜索。根据不同的 Ut 构造方法有不同的拟牛顿法。
注意拟牛顿法的 关键词:
2.2 拟牛顿条件
牛顿法的搜索方向是
d(t)=−H−1tgt
为了不算二阶导及其逆矩阵,设法构造一个矩阵 U,用它来逼近 H−1
现在为了方便推导,假设 f(x) 是二次函数,于是 Hesse 矩阵 H 是常数阵,任意两点 x(t) 和 x(t+1) 处的梯度之差是:
▽f(x(t+1))−▽f(x(t))=H⋅(x(t+1)−x(t))
等价于
x(t+1)−x(t)=H−1⋅[▽f(x(t+1))−▽f(x(t))]
那么对非二次型的情况,也仿照这种形式,要求近似矩阵 U 满足类似的关系:
x(t+1)−x(t)=Ut+1⋅[▽f(x(t+1))−▽f(x(t))]
或者写成
Δxt=Ut+1⋅Δgt
以上就是拟牛顿条件,不同的拟牛顿法,区别就在于如何确定 U。
2.3 DFP法
为了方便区分,下面把U称作D(表示DFP)。
DFP推导
现在已知拟牛顿条件
Δxt=Dt+1⋅Δgt
假设已知Dt,希望用叠加的方式求Dt+1,即 Dt+1=Dt+ΔDt,代入得到
ΔDtΔgt=Δxt−DtΔgt
假设满足这个等式的 ΔDt 是这样的形式:
ΔDt=Δxt⋅qTt−DtΔgt⋅wTt
首先,对照一下就能发现:
qTt⋅Δgt=wTt⋅Δgt=In
其次,要保证 ΔDt 是对称的,参照 ΔDt 的表达式,最简单就是令
qt=αtΔxtwt=βtDtΔgt
第二个条件代入第一个得到:αt=1ΔgTtΔxtβt=1ΔgTtDtΔgt
然后代入回ΔDt 的表达式:
ΔDt=ΔxtΔxTtΔgTtΔxt−DtΔgtΔgTtDtΔgTtDtΔgt
观察一下两项分式,第一项仅涉及向量乘法,时间复杂度是O(n),第二项涉及矩阵乘法,时间复杂度是O(n2),综合起来是O(n2)。
DFP算法步骤
(1)给定初始点 x(0),允许误差 ϵ,令 D0=In(n是x的维数),t=0
(2)计算搜索方向 d(t)=−D−1t⋅gt
(3)从点 x(t) 出发,沿着 d(t) 做一维搜索,获得最优步长并更新参数:
λt=argminλf(x(t)+λ⋅d(t))x(t+1)=x(t)+λt⋅d(t)
(4)判断精度,若|gt+1|<ϵ则停止迭代,否则转(5)
(5)计算Δg=gt+1−gt,Δx=x(t+1)−x(t),更新 H
Dt+1=Dt+ΔxΔxTΔgTΔx−DtΔgΔgTDtΔgTDtΔg
(6)t=t+1,转(2)
2.4 BFGS法
为了方便区分,下面把U称作B−1(表示BFGS)。
BFGS推导
拟牛顿条件
Δxt=B−1t+1⋅ΔgtΔgt=Bt+1⋅Δxt
推导与DFP相似,但是,可以看到BFGS这种拟牛顿条件的形式与BFP的是对偶的,所以迭代公式只要把 Δxt 和 Δgt 调换一下就好。
ΔBt=ΔgtΔgTtΔxTtΔgt−BtΔxtΔxTtBtΔxTtBtΔxt
只不过有个问题,按照下面这个迭代公式,不也一样要求逆吗?这就要引入谢尔曼莫里森公式了。
Δxt=B−1t+1⋅Δgt
Sherman-Morrison 公式
对于任意非奇异方阵A,u,v∈Rn是n维向量,若1+vTA−1u≠0,则
(A+uvT)−1=A−1−(A−1u)(vTA−1)1+vTA−1u
该公式描述了在矩阵A发生某种变化时,如何利用之前求好的逆,求新的逆。
对迭代公式引入两次 Sherman-Morrison 公式就能得到
B−1t+1=(In−ΔxtΔgTtΔxTtΔgt)B−1t(In−ΔgtΔxTtΔxTtΔgt)+ΔxtΔxTtΔxTtΔgt
就得到了逆矩阵之间的推导。可能有人会问,第一个矩阵不也要求逆吗?其实这是一个迭代算法,初始矩阵设为单位矩阵(对角阵也可以)就不用求逆了。
这个公式的详细推导可以参考这里或者这里。
BFGS算法步骤
虽然下面的矩阵写成B−1,但要明确,BFGS从头到尾都不需要算逆,把下面的B−1换成H这个符号,也是一样的。
(1)给定初始点 x(0),允许误差 ϵ,设置 B−10,t=0
(2)计算搜索 d(t)=−B−1t⋅gt
(3)从点 x(t) 出发,沿着 d(t) 做一维搜索,获得最优步长并更新参数:
λt=argminλf(x(t)+λ⋅d(t))x(t+1)=x(t)+λt⋅d(t)
(4)判断精度,若|gt+1|<ϵ则停止迭代,否则转(5)
(5)计算Δg=gt+1−gt,Δx=x(t+1)−x(t),更新 B−1,然后
B−1t+1=(In−ΔxtΔgTtΔxTtΔgt)B−1t(In−ΔgtΔxTtΔxTtΔgt)+ΔxtΔxTtΔxTtΔgt
(6)t=t+1,转(2)
2.5 L-BFGS法(Limited-memory BFGS)
对于d维参数,BFGS算法需要保存一个O(d2)大小的B−1矩阵,实际上只需要每一轮的Δx和Δg,也可以递归计算出当前迭代的B−1矩阵,L-BFGS就是基于这种思想,实现了节省内存的BFGS。
L-BFGS推导
BFGS的递推公式:
B−1t+1=(In−ΔxtΔgTtΔxTtΔgt)B−1t(In−ΔgtΔxTtΔxTtΔgt)+ΔxtΔxTtΔxTtΔgt
现在假设ρt=1ΔxTtΔgt,Vt=In−ρtΔgtΔxTt,则递推公式可以写成
B−1t+1=VTtB−1tVt+ρtΔxtΔxTt
给定的初始矩阵B−10后,之后的每一轮都可以递推计算
B−11=VT0B−10V0+ρ0Δx0ΔxT0B−12=VT1B−10V1+ρ1Δx1ΔxT1=(VT1VT0)B−10(V0V1)+VT1ρ0Δx0ΔxT0V1+ρ1Δx1ΔxT1
一直到最后B−1k+1可以由t=0到t=k的Δxt和Δgt表示:
B−1t+1=++++(VTtVTt−1⋯VT1VT0)B−10(V0⋯Vt−1Vt)(VTtVTt−1⋯VT2VT1)(ρ0Δx0ΔxT0)(V1⋯Vt−1Vt)⋯VTt(ρt−1Δxt−1ΔxTt−1)VtρtΔxtΔxTt
看起来很长,其实可以写成一个求和项
B−1t+1=(∏i=t0VTi)B−10(∏i=0tVi)+∑j=0t(∏i=tj+1VTi)(ρjΔxjΔxTj)(∏i=j+1tVi)
这个求和项包含了从0到t的所有Δx和Δg,而根据实际需要,可以只取最近的m个,也就是:
B−1t=(∏i=t−1t−mVTi)B−10(∏i=t−mt−1Vi)+∑j=t−1t−m(∏i=tj+1VTi)(ρjΔxjΔxTj)(∏i=j+1tVi)
工程上的L-BFGS
我们关心的其实不是B−1t本身如何,算B−1t的根本目的是要算本轮搜索方向 B−1tgt
以下算法摘自《Numerical Optimization》,它可以高效地计算出拟牛顿法每一轮的搜索方向。仔细观察一下,你会发现它实际上就是复现上面推导的那一堆很长的递推公式,你所需要的是最近m轮的Δx和Δg,后向和前向算完得到最终的 r 就是搜索方向 B−1tgt,之后要做一维搜索或者什么的都可以。
解释一下算法的符号和本文符号之间的对应关系,si=Δxi,yi=Δgi,Hk=B−1k
代码实现可以参考这里。
L-BFGS算法步骤
(1)给定初始点 x(0),允许误差 ϵ,预定保留最近m个向量,设置 B−10,t=0
(2)用Algorithm 9.1计算搜索方向 d(t)=−B−1t⋅gt
(3)从点 x(t) 出发,沿着 d(t) 做一维搜索,获得最优步长并更新参数:
λt=argminλf(x(t)+λ⋅d(t))x(t+1)=x(t)+λt⋅d(t)
(4)判断精度,若|gt+1|<ϵ则停止迭代,否则转(5)
(5)判断 t>m,删掉存储的 Δxt−m 和 Δgt−m
(5)计算Δg=gt+1−gt,Δx=x(t+1)−x(t),令t=t+1,转(2)
最后,有时候你看不懂BFGS到底意味着什么,并不是你英文差,而是因为这个简称真的没有意义。。。。。
参考资料
- 【博客】LBFGS方法推导-慢慢的回味
- 【博客】数值优化:理解L-BFGS算法
- 【博客】无约束优化算法——牛顿法与拟牛顿法(DFP,BFGS,LBFGS)
- 【博客】无约束最优化方法——牛顿法、拟牛顿法、BFGS、LBFGS
- 【博客】Numerical Optimization: Understanding L-BFGS
- 【论文】A Stochastic Quasi-Newton Method for Online Convex Optimization
-
【书籍】Numeric Optimization