本文正在参加「金石计划 . 分割6万现金大奖」

前语

在求解机器学习算法的模型参数,即无约束优化问题时,梯度下降(Gradient Descent) 是最常选用的办法之一,另一种常用的办法是最小二乘法。

在 【AI】浅谈梯度下降算法(理论篇) 这篇博文中,咱们现已学习了梯度下降算法的一些基本概念以及理论推导,接下来,咱们将经过结合代码进行实战,理论与实践相结合,加深对知识点的理解;

大家族

尽管说是梯度下降,但其实它还是个巨大的家族,就类似于编程言语有 C、Java、Python 等之分,梯度下降算法也被分为了几大类,主要的有 BGD、SGD、MBGD:

  • 批量梯度下降法(Batch Gradient Descent) : 梯度下降法最常用的形式,具体做法也便是在更新参数时运用一切的样原本进行更新;

    i=i−∑j=0m(h(x0(j),x1(j),…,xn(j))−yj)xi(j)_i=_i−∑_{j=0}^m(h_(x^{(j)}_0,x^{(j)}_1,…,x^{(j)}_n)−y_j)x_i^{(j)}

    长处:大局最优解,易于并行完成;
    缺点:计算价值大,数据量大时,训练进程慢;

  • 随机梯度下降法(Stochastic Gradient Descent) : 和批量梯度下降法原理类似,区别在于求梯度时,没有用一切的 mm 个样本的数据,而是仅仅选取一个样本 jj 来求梯度;

    i=i−(h(x0(j),x1(j),…,xn(j))−yj)xi(j)_i=_i−(h_(x^{(j)}_0,x^{(j)}_1,…,x^{(j)}_n)−y_j)x_i^{(j)}

    长处:训练速度快;
    缺点:准确度下降,并不是大局最优,不易于并行完成;

  • 小批量梯度下降法(Mini-batch Gradient Descent) : 小批量梯度下降法是批量梯度下降法和随机梯度下降法的折中,也便是关于 mm 个样本,咱们选用 xx 个样原本迭代,1<x<m1<x<m。一般能够取 x=10x=10,当然根据样本的数据量,能够调整这个 xx 的值;

    i=i−∑j=tt+x−1(h(x0(j),x1(j),…,xn(j))−yj)xi(j)_i=_i−∑_{j=t}^{t+x-1}(h_(x^{(j)}_0,x^{(j)}_1,…,x^{(j)}_n)−y_j)x_i^{(j)}

    前两种办法的功能折中;

一维问题

例1:求 f(x)=x2+1f(x) = x^2 + 1 的最小值

【AI】浅谈梯度下降算法(实战篇)

f(x)=x2+1f(x) = x^2 + 1

运用梯度下降法求 f(x)=x2+1(−10≤x≤10)f(x) = x^2 + 1 \quad (-10 \leq x \leq 10) 的最小值

因为 f(x)=x2+1f(x) = x^2 + 1 是凸函数,从图中也能够一眼看出,其最小值就在 x=0x=0 处;

接下来就运用梯度下降法进行求解:

1、方针函数,即 f(x)=x2+1f(x) = x^2 + 1

def func_target(x):
    return x ** 2 + 1

2、求解梯度,即 f(x)′=2xf(x)^{‘} = 2x

def func_gradient(x):
    return x * 2

3、梯度下降算法,需要注意几个参数的意义:

  • x : 当时 x 的值,能够经过参数供给初始值;
  • learn_rate : 学习率,相当于设置的步长;
  • precision : 收敛精度;
  • max_iters : 最大迭代次数;
def SGD(x=1, learn_rate=0.1, precision=1e-5, max_iters=10000):
    for i in range(max_iters):
        grad_cur = func_gradient(x)
        if abs(grad_cur) < precision:
            break
        x = x - learn_rate * grad_cur
        print(f"第 {i+1} 次迭代: x 值为 {x}, y 值为 {func_target(x)}")
    print(f"\n最小值 x = {x}, y = {func_target(x)}")
    return x
if __name__ == '__main__':
    SGD(x=10, learn_rate=0.2)

【AI】浅谈梯度下降算法(实战篇)

例2:求 12[(x1+x2−4)2+(2×1+3×2−7)2]\frac{1}{2}[(x_1+x_2-4)^2 + (2x_1+3x_2-7)^2] 的极值

经过梯度下降的办法成功求得了 的最小值之后是不是信心大增呢,接下来让咱们逐渐加深难度:运用梯度下降法求多项式 12[(x1+x2−4)2+(2×1+3×2−7)2]\frac{1}{2}[(x_1+x_2-4)^2 + (2x_1+3x_2-7)^2] 的极值

在运用梯度下降求解这道题的进程中,就不得不注意到一个问题:梯度下降或许在部分最小的点收敛

【AI】浅谈梯度下降算法(实战篇)

1、方针函数,即 12[(x1+x2−4)2+(2×1+3×2−7)2\frac{1}{2}[(x_1+x_2-4)^2 + (2x_1+3x_2-7)^2

def func_target(x1, x2):
    return ((x1 + x2 - 4) ** 2 + (2*x1 + 3*x2 -7) ** 2) * 0.5

2、求解梯度,即 ∂f∂x1=(x1+x2−4)+2(2×1+3×2−7)\frac{∂f}{∂x_1} = (x_1+x_2-4)+2(2x_1+3x_2-7)∂f∂x2=(x1+x2−4)+3(2×1+3×2−7)\frac{∂f}{∂x_2} = (x_1+x_2-4)+3(2x_1+3x_2-7)

def func_gradient(x1, x2):
    grad_x1 = (x1 + x2 - 4) + 2 * (2*x1 + 3*x2 -7)
    grad_x2 = (x1 + x2 - 4) + 3 * (2*x1 + 3*x2 -7)
    return grad_x1, grad_x2

3、梯度下降算法:

def SGD(x1=0, x2=0, learn_rate=0.01, precision=1e-6, max_iters=10000):
    y1 = func_target(x1, x2)
    for i in range(max_iters):
        grad_x1, grad_x2 = func_gradient(x1, x2)
        x1 = x1 - learn_rate * grad_x1
        x2 = x2 - learn_rate * grad_x2
        y2 = func_target(x1, x2)
        if (y1 - y2) < precision:
            break
        if y2 < y1: y1 = y2
        print(f"第 {i+1} 次迭代: x1 值为 {x1}, x2 值为 {x2}, 输出值为 {y2}")
    print(f"该多项式的极小值为 {y2}, ({x1}, {x2})")
    return x1, x2, y2
if __name__ == '__main__':
    SGD()

【AI】浅谈梯度下降算法(实战篇)

【AI】浅谈梯度下降算法(实战篇)

中心的迭代进程就省掉了;

二维问题

当你经过自己的努力完成前两个例子之后,你是不是现已不满足于一维问题了呢,那么接下来咱们进入二维问题:运用梯度下降法求 f(x,y)=−e−(x2+y2)f(x,y) = -e^{-(x^2+y^2)}[0,0][0,0] 处有最小值

【AI】浅谈梯度下降算法(实战篇)

f(x,y)=−e−(x2+y2)f(x,y) = -e^{-(x^2+y^2)}

经过这个例子,咱们会发现梯度下降的局限性,先在这里留个悬念;

1、方针函数,即 f(x,y)=−e−(x2+y2)f(x,y) = -e^{-(x^2+y^2)}

def func_target(cell):
    :param cell: 二维向量
    return -math.exp(-(cell[0] ** 2 + cell[1] ** 2))

2、求解梯度,即 ∂f∂x=2xe−(x2+y2)\frac{∂f}{∂x} = 2xe^{-(x^2+y^2)}∂f∂y=2ye−(x2+y2)\frac{∂f}{∂y} = 2ye^{-(x^2+y^2)}

def func_gradient(cell):
    :param cell: 二维向量
    grad_x = 2 * cell[0] * math.exp(-(cell[0] ** 2 + cell[1] ** 2))
    grad_y = 2 * cell[1] * math.exp(-(cell[0] ** 2 + cell[1] ** 2))
    return np.array([grad_x, grad_y])

3、梯度下降算法:

def SGD(x=np.array([0.1, 0.1]), learn_rate=0.1, precision=1e-6, max_iters=10000):
    for i in range(max_iters):
        grad_cur = func_gradient(x)
        if np.linalg.norm(grad_cur, ord=2) < precision:
            break
        x = x - learn_rate * grad_cur
        print(f"第 {i+1} 次迭代: x 值为 {x}, y 值为 {func_target(x)}")
    print(f"\n最小值 x = {x}, y = {func_target(x)}")
    return x

4、当 x0x0的初始值设为[1,−1][1,−1] 时,一切都显得很正常:

【AI】浅谈梯度下降算法(实战篇)

5、但当咱们把 x0x0的初始值设为[3,−3][3,−3] 时,成果是出人意料的:

【AI】浅谈梯度下降算法(实战篇)

梯度下降法没有找到真实的极小值点!

局限性

继续讲述上面的非预期成果:

假如仔细观察方针函数的图像,以及梯度下降法的算法原理,你就很简单发现问题所在了。[3,−3][3,−3]处的梯度就几乎为 0 了!

因为“梯度过小”,梯度下降法或许无法确定行进的方向了。即使人为增加收敛条件中的精度,也会因为梯度过小,导致迭代中行进的步长距离过小,循环时间过长。

梯度下降法完成简单,原理也易于理解,但它有自身的局限性,因而有了后边许多算法对它的改进。

关于梯度过小的状况,梯度下降法或许难以求解。

此外,梯度下降法合适求解只有一个部分最优解的方针函数,关于存在多个部分最优解的方针函数,一般状况下梯度下降法不保证得到大局最优解(因为凸函数有个性质是只存在一个部分最优解,一切也有文献的提法是:当方针函数是凸函数时,梯度下降法的解才是大局最优解)。

因为泰勒公式的展开是近似公式,要求迭代步长要满足小,因而梯度下降法的收敛速度并非很快的。

跋文

上述便是本篇博文的一切内容了,经过实战对梯度下降知识点进行巩固和加深印象,并且层层收入,期望读者能有所收成!

关于理论还不是很清楚的读者,能够回看上篇博文:【AI】浅谈梯度下降算法(理论篇);

参考:

  • 梯度下降(Gradient Descent)
  • Python 完成简单的梯度下降法
  • 梯度下降法原理与python完成

上篇精讲:【AI】浅谈梯度下降算法(理论篇)

我是,等待你的关注;

创造不易,请多多支撑;

系列专栏:AI