1. 梯度下降法
梯度下降法与现在火热的机器学习、深度学习息息相关,相关的文章非常多。其基本思路可以理解为一种启发式搜索算法,每次迭代都寻找附近一定范围内的最小值。
基本步骤是:
使用拉格朗日法对一般的凸优化问题进行转化,假设问题为min L(x) L ( x ) ,从一个初始解 x0 x 0 出发,计算当前点的一阶导数 L′(x0) L ′ ( x 0 ) ,然后按照一定的步长 α α 改变 x0 x 0 的值,变为 x1=x0−αL′(x0) x 1 = x 0 − α L ′ ( x 0 ) ,目标函数从 L(x0) L ( x 0 ) 变为 L(x1) L ( x 1 ) 。如此迭代下去,直至 L(xi) L ( x i ) 不再减小为止。如果 α α 足够小,不难看出终止条件就是 L′(xi)=0 L ′ ( x i ) = 0
如果问题是非凸的,那么使用一阶导数还不够,很可能会陷入“鞍点”。此外,非凸问题常常有多个局部最优,梯度下降法作为一种“短视”算法,只能找到局部最优解。
2. 凸优化问题的梯度下降法python代码
令L为优化函数,LG为函数的导数,x为初始值,delta为步长,tol为精度,则梯度下降的代码为
import numpy as np
def GD(L,LG,x,delta,tol):
print(str(x)+":"+str(L(x)))
xn = x - delta * LG(x)
if L(x)>L(xn)+tol:
GD(L,LG,xn,delta,tol)
求解的例子为min L=(x0−2)2+(x1−1)2 L = ( x 0 − 2 ) 2 + ( x 1 − 1 ) 2 ,导数为[ 2(x0−2),2(x1−1) 2 ( x 0 − 2 ) , 2 ( x 1 − 1 ) ],初始值为[0,0],不难看出,最优解为0,在[2,1]处取得。代码为:
def L(x):
return (x[0]-2)*(x[0]-2) + (x[1]-1)*(x[1]-1)
def LG(x):
return np.array([2*(x[0]-2),2*(x[1]-1)])
GD(L,LG,np.array([0,0]),0.1,0.0001)
结果输出为:
[0 0]:5
[0.4 0.2]:3.2000000000000006
[0.72 0.36]:2.047999999999999
[0.976 0.488]:1.3107199999999999
[1.1808 0.5904]:0.8388607999999999
[1.34464 0.67232]:0.5368709119999999
[1.475712 0.737856]:0.34359738367999987
[1.5805696 0.7902848]:0.21990232555519995
[1.66445568 0.83222784]:0.1407374883553279
[1.73156454 0.86578227]:0.09007199254740988
[1.78525164 0.89262582]:0.05764607523034231
[1.82820131 0.91410065]:0.03689348814741904
[1.86256105 0.93128052]:0.023611832414348215
[1.89004884 0.94502442]:0.015111572745182858
[1.91203907 0.95601953]:0.009671406556917048
[1.92963126 0.96481563]:0.006189700196426927
[1.943705 0.9718525]:0.003961408125713221
[1.954964 0.977482]:0.0025353012004564663
[1.9639712 0.9819856]:0.0016225927682921462
[1.97117696 0.98558848]:0.0010384593717069706
[1.97694157 0.98847078]:0.0006646139978924637
[1.98155326 0.99077663]:0.00042535295865118083
[1.9852426 0.9926213]:0.00027222589353675247
停止迭代时,最优值为0.00027222589353675247,在[1.9852426 0.9926213]处取得。