机器学习中很多模型的参数估计都要用到优化算法,梯度下降是其中最简单也用得最多的优化算法之一。梯度下降(Gradient Descent)[3]也被称之为最快梯度(Steepest Descent),可用于寻找函数的局部最小值。梯度下降的思路为,函数值在梯度反方向下降是最快的,只要沿着函数的梯度反方向移动足够小的距离到一个新的点,那么函数值必定是非递增的,如图1所示。
梯度下降思想的数学表述如下:
其中x0,x1,⋯,xn:
对应的各点函数值序列之间的关系为:
很显然,当dk满足以下关系:
当dk都可以作为搜素方向。一般搜索方向表述为如下形式:
其中
Line Search
在给定搜索方向dk的前提下,线性搜索要解决的问题如下:
如果α⋆的近似值,下面选择几种典型的介绍。
Bisection Search
二分线性搜索(Bisection Line Search)[2]可用于求解函数的根,其思想很简单,就是不断将现有区间划分为两半,选择必定含有使[αl,αh]的长度为:
由迭代的终止条件之一αh−αl≥ϵ知迭代次数的上界为:
下面给出二分搜索的Python代码
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
Backtracking
回溯线性搜索(Backing Line Search)[1]基于Armijo准则计算搜素方向上的最大步长,其基本思想是沿着搜索方向移动一个较大的步长估计值,然后以迭代形式不断缩减步长,直到该步长使得函数值f(xk)的减小程度大于期望值(满足Armijo准则)为止。Armijo准则(见图3)的数学描述如下:
其中0<c1<1,则有
根据导数的基本定义,结合上式,有如下关系:
因此,存在一个步长α∈(0,α^),下式均成立
即∀α∈(0,α^),f(xk+αdk)<f(xk)+cαf′(xk)Tdk。 下面给出基于Armijo准则的线性搜索Python代码:
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
Interpolation
基于Armijo准则的回溯线性搜索的收敛速度无法得到保证,特别是要回退很多次后才能落入满足Armijo准则的区间。如果我们根据已有的函数值和导数信息,采用多项式插值法(Interpolation)[12,6,5,9]拟合函数,然后根据该多项式函数估计函数的极值点,这样选择合适步长的效率会高很多。 假设我们只有hq(α)
注意,该二次函数满足hq(α)的最小值估计下一个步长:
如果hc(α),如图4(b)所示
其中
对αi+1∈[0,αi]的形式如下:
利用以上的三次插值函数求解下一个步长的过程不断重复,直到步长满足条件为止。如果出现αi+1≈0。 但是,在很多情况下,计算函数值后只需付出较小的代价就能顺带计算出导数值或其近似值,这使得我们可以用更精确的三次Hermite多项式[6]进行插值,如图4(c)所示