运筹系列6:凸优化梯度下降法python代码

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=(x02)2+(x11)2 L = ( x 0 − 2 ) 2 + ( x 1 − 1 ) 2 ,导数为[ 2(x02),2(x11) 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]处取得。

点赞