机器学习中很多模型的参数估计都要用到优化算法,梯度下降是其中最简单也用得最多的优化算法之一。梯度下降(Gradient Descent)[3]也被称之为最快梯度(Steepest Descent),可用于寻找函数的局部最小值。梯度下降的思路为,函数值在梯度反方向下降是最快的,只要沿着函数的梯度反方向移动足够小的距离到一个新的点,那么函数值必定是非递增的,如图1所示。

Line Search and Quasi-Newton Methods 线性搜索与拟牛顿法

梯度下降思想的数学表述如下:

(1)b=a−α∇F(a)⇒f(a)≥f(b)

其中x0,x1,⋯,xn:

(2)xk+1=xk−αk∇f(xk),0≤k≤n

对应的各点函数值序列之间的关系为:

(3)f(x0)≥f(x1)≥f(x2)≥⋯≥f(xn)

很显然,当dk满足以下关系:

(4)f(xk+αdk)<f(xk)∀α∈(0,ϵ]

dk都可以作为搜素方向。一般搜索方向表述为如下形式:

(5)dk=−Bk∇f(xk)

其中

 

Line Search

在给定搜索方向dk的前提下,线性搜索要解决的问题如下:

(6)α=argminα≥0h(α)=argminα≥0f(xk+αdk)

如果α⋆的近似值,下面选择几种典型的介绍。

 

Bisection Search

二分线性搜索(Bisection Line Search)[2]可用于求解函数的根,其思想很简单,就是不断将现有区间划分为两半,选择必定含有使[αl,αh]的长度为:

(7)L=(12)nα^

由迭代的终止条件之一αh−αl≥ϵ知迭代次数的上界为:

(8)L≤ϵ⇒k≤[log2⁡(α^ϵ)]

下面给出二分搜索的Python代码

 

Line Search and Quasi-Newton Methods 线性搜索与拟牛顿法
 1 def bisection(dfun,theta,args,d,low,high,maxiter=1e4):
 2     """
 3     #Functionality:find the root of the function(fun) in the interval [low,high]
 4     #@Parameters
 5     #dfun:compute the graident of function f(x)
 6     #theta:Parameters of the model
 7     #args:other variables needed to compute the value of dfun
 8     #[low,high]:the interval which contains the root
 9     #maxiter:the max number of iterations
10     """
11     eps=1e-6
12     val_low=np.sum(dfun(theta+low*d,args)*d.T)
13     val_high=np.sum(dfun(theta+high*d,args)*d.T)
14     if val_low*val_high>0:
15         raise Exception('Invalid interval!')
16     iter_num=1
17     while iter_num<maxiter:
18         mid=(low+high)/2
19         val_mid=np.sum(dfun(theta+mid*d,args)*d.T)
20         if abs(val_mid)<eps or abs(high-low)<eps:
21             return mid
22         elif val_mid*val_low>0:
23             low=mid
24         else:
25             high=mid
26         iter_num+=1
Line Search and Quasi-Newton Methods 线性搜索与拟牛顿法

Backtracking

回溯线性搜索(Backing Line Search)[1]基于Armijo准则计算搜素方向上的最大步长,其基本思想是沿着搜索方向移动一个较大的步长估计值,然后以迭代形式不断缩减步长,直到该步长使得函数值f(xk)的减小程度大于期望值(满足Armijo准则)为止。Armijo准则(见图3)的数学描述如下:

(9)f(xk+αdk)≤f(xk)+c1αf′(xk)Tdk

其中0<c1<1,则有

(10)h′(0)<c1h′(0)<0

根据导数的基本定义,结合上式,有如下关系:

(11)h′(0)=limα→0h(α)−h(0)α=limα→0f(xk+αdk)−f(xk)α<ch′(0)

因此,存在一个步长α∈(0,α^),下式均成立

(12)f(xk+αdk)−f(xk)α<cf′(xk)Tdk

∀α∈(0,α^),f(xk+αdk)<f(xk)+cαf′(xk)Tdk。 下面给出基于Armijo准则的线性搜索Python代码:

 

Line Search and Quasi-Newton Methods 线性搜索与拟牛顿法
 1 def ArmijoBacktrack(fun,dfun,theta,args,d,stepsize=1,tau=0.5,c1=1e-3):
 2     """
 3     #Functionality:find an acceptable stepsize via backtrack under Armijo rule
 4     #@Parameters
 5     #fun:compute the value of objective function
 6     #dfun:compute the gradient of objective function
 7     #theta:a vector of parameters of the model
 8     #stepsize:initial step size
 9     #c1:sufficient decrease Parameters
10     #tau:rate of shrink of stepsize
11     """
12     slope=np.sum(dfun(theta,args)*d.T)
13     obj_old=costFunction(theta,args)
14     theta_new=theta+stepsize*d
15     obj_new=costFunction(theta_new,args)
16     while obj_new>obj_old+c1*stepsize*slope:
17         stepsize*=tau
18         theta_new=theta+stepsize*d
19         obj_new=costFunction(theta_new,args)
20     return stepsize
Line Search and Quasi-Newton Methods 线性搜索与拟牛顿法

Interpolation

基于Armijo准则的回溯线性搜索的收敛速度无法得到保证,特别是要回退很多次后才能落入满足Armijo准则的区间。如果我们根据已有的函数值和导数信息,采用多项式插值法(Interpolation)[12,6,5,9]拟合函数,然后根据该多项式函数估计函数的极值点,这样选择合适步长的效率会高很多。 假设我们只有hq(α)

(13)hq(α)=(h(α0)−h(0)−α0h′(0)α02)α2+h′(0)α+h(0)

注意,该二次函数满足hq(α)的最小值估计下一个步长:

(14)α1=h′(0)α022[h(0)+h′(0)α0−h(α0)]

如果hc(α),如图4(b)所示

(15)hc(α)=aα3+bα2+h′(0)α+h(0)

其中

(16)[ab]=1αi−12αi2(αi−αi−1)[αi−12−αi2−αi−13αi3][h(αi)−h(0)−h′(0)αih(αi−1)−h(0)−h′(0)αi−1]

αi+1∈[0,αi]的形式如下:

(17)αi+1=−b+b2−3ah′(0)3a

利用以上的三次插值函数求解下一个步长的过程不断重复,直到步长满足条件为止。如果出现αi+1≈0。 但是,在很多情况下,计算函数值后只需付出较小的代价就能顺带计算出导数值或其近似值,这使得我们可以用更精确的三次Hermite多项式[6]进行插值,如图4(c)所示

相关文章:

  • 2021-08-18
  • 2021-06-28
  • 2021-06-28
  • 2021-08-20
  • 2021-09-08
  • 2021-12-30
  • 2022-03-04
猜你喜欢
  • 2021-07-01
  • 2021-08-27
  • 2022-01-13
  • 2022-12-23
  • 2021-10-28
  • 2021-09-28
相关资源
相似解决方案