算法实践-梯度下降(GD)

梯度下降

以一个简单的实例,理解梯度下降。

问题: y = sin ⁡ x cos ⁡ x − 2 y = \frac{{\sin x}}{{ \cos x-2 }} y=cosx2sinx, x ∈ ( 0 , π ) x \in (0,\pi ) x(0,π) 求y的最小值。

显然,面对这个简单的函数我们可以很轻易的画出其函数图像,可以看到在 ( 0 , π ) (0,\pi ) (0,π)中存在唯一极值。
在这里插入图片描述啊

解析解:
题目的函数是可导的,废话不多说直接求导,可以得到:

y ′ = cos ⁡ x ( cos ⁡ x − 2 ) + sin ⁡ 2 x ( cos ⁡ − 2 ) 2 = 0 ⇒ cos ⁡ x ( cos ⁡ x − 2 ) + sin ⁡ 2 x = 0 ⇒ − 2 cos ⁡ x + 1 = 0 ⇒ cos ⁡ x = 1 2 , x ∈ ( 0 , π ) \begin{array}{l} y' = \frac{{ \cos x( \cos x-2) + {{\sin }^2}x}}{{{{(\cos-2 )}^2}}} = 0\\ \\ \Rightarrow \cos x(\cos x-2) + {\sin ^2}x = 0\\ \\ \Rightarrow - 2\cos x + 1 = 0\\ \\ \Rightarrow \cos x = \frac{1}{2},x \in (0,\pi ) \end{array} y=(cos2)2cosx(cosx2)+sin2x=0cosx(cosx2)+sin2x=02cosx+1=0cosx=21x(0,π)

即当 x = π 3 x = \frac{\pi }{3} x=3π时,y取得极值 y min ⁡ = − 3 3 {y_{\min }} = - \frac{{\sqrt 3 }}{3} ymin=33


梯度下降:

换一个思路,如果把函数看成是一个优化问题,那么问题就变成:

min ⁡ y = sin ⁡ ( x ) cos ⁡ ( x ) − 2 s . t . 0 < x < π \begin{array}{l} \min {\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} y = \frac{{\sin (x)}}{{\cos (x) - 2}}\\ s.t.{\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} 0 < x < \pi \end{array} miny=cos(x)2sin(x)s.t.0<x<π

梯度下降的核心思想很简单,极值点导数(多维就是偏导数)为0,那么沿着梯度大的地方走,直到走不动(梯度接近于0)为止,这样就能最快到达底部,找到函数极小值,反之上升则极大值。

在这里插入图片描述

Python 代码如下:

"""
梯度下降简单示例
"""
import numpy as np
import matplotlib.pyplot  as plt

def func_fx(x):
    """目标函数"""
    return np.sin(x)/(np.cos(x)-2)

def grad_fx(x):
    """ 目标函数1阶导数y'=(1-2*cosx)/(cosx-2)^2"""
    return (1-2*np.cos(x))/(np.cos(x)-2)**2

def gradient_descent(grad, cur_x=0.1, learning_rate=0.01, precision=0.0001, max_iters=10000):
    """
    :param grad: 目标函数梯度
    :param cur_x: 当前的x值
    :param learning_rate: 学习率
    :param precision: 收敛精度
    :param max_iters: 最大迭代次数
    :return: x_min
    """
    for i in range(max_iters):
        grad_cur = grad(cur_x)
        if abs(grad_cur) < precision: #当梯度收敛到接近0结束
           break  
        cur_x = cur_x - grad_cur * learning_rate
        print("第", i, "次迭代:x 值为 ", cur_x)
        plt.plot(cur_x,func_fx(cur_x),'.',color='b')
    plt.show()
    return cur_x

if __name__ == '__main__':
    # cur_x can be any number between 0 and pi
    xmin = gradient_descent(grad_fx, cur_x=0.1, learning_rate=0.01, precision=0.0001, max_iters=2000)
    print("局部最小值 xmin =",xmin)
    print("局部最小值 ymin =", func_fx(xmin))

类似的方法—牛顿法

类似的方法还有牛顿法,与梯度下降不同,简单来说,梯度下降奔着目标函数最小值去,通过梯度判断方向, min ⁡ f ( x ) \min {\kern 1pt} {\kern 1pt} {\kern 1pt} f(x) minf(x);而牛顿法则是奔着目标函数导数为零去, min ⁡ f ′ ( x ) \min {\kern 1pt} {\kern 1pt} {\kern 1pt} f'(x) minf(x),间接的求目标函数极小值。公示可以写成:

在这里插入图片描述
当θ是向量时,牛顿法可以使用下面式子表示:
在这里插入图片描述
其中H叫做Hessian矩阵,其实就是目标函数对参数θ的二阶导数。
通过比较牛顿法和梯度下降法的迭代公式,可以发现两者及其相似,两者都是迭代求解。Hessian矩阵的逆就好比梯度下降法的学习率参数alpha。牛顿法收敛速度相比梯度下降法很快,而且由于Hessian矩阵的的逆在迭代中不断减小,起到逐渐缩小步长的效果。但其缺点也很明显,每一次迭代需要求解Hessian的逆矩阵,当样本量很大时,需要求一个超级大的逆矩阵,这时就很难或者很慢才能求解解析解了,使用迭代的梯度下降法比较有优势。总之,使用牛顿法/拟牛顿法收敛更快,但是每次迭代的时间比梯度下降法长。梯度下降每次迭代时间很短,且构造简单,被广泛应用。


梯度下降法大家族(BGD,SGD,MBGD)

基本概念和变量的定义:

  1. 假设有n个样本: ( x i , y i ) ( i = 1 , 2.... n ) (x^i,y^i)\left( i=1,2....n \right) (xi,yi)(i=1,2....n),每个样本特征 x i x^i xi与样本输出 y i y^i yi一一对应,即训练的数据。

  2. 假设函数: f θ ( x ) = θ 1 x 1 + . . . + θ n x n = ∑ i = 0 n θ i x i f_{\theta}(x)={\theta}_1x1+...+{\theta}_nx_n=\sum_{i=0}^n{\theta_ix_i} fθ(x)=θ1x1+...+θnxn=i=0nθixi f θ ( x ) f_\theta(x) fθ(x)即监督学习中要学习的模型, θ \theta θ为模型参数,最终学习(训练)完得到 f θ ( x ) f_\theta(x) fθ(x),对于新的 x ^ \widehat{x} x ,可以得到预测值 y ^ = f θ ( x ^ ) \widehat{y}=f_\theta(\widehat{x}) y =fθ(x )

  3. 步长:α

1.批量梯度下降法(Batch Gradient Descent)

批量梯度下降法,具体做法也就是在更新参数时使用所有的样本来进行更新。
θ i = θ i − α ∑ j = 1 n ( f θ ( x 0 ( j ) , x 1 ( j ) , . . . x n ( j ) ) − y j ) x i ( j ) \mathrm{\theta}_{\mathrm{i}}=\mathrm{\theta}_{\mathrm{i}}-\mathrm{\alpha}\sum_{\mathrm{j}=1}^{\mathrm{n}}{\left( f_{\mathrm{\theta}}\left( \mathrm{x}_{0}^{\left( \mathrm{j} \right)},\mathrm{x}_{1}^{\left( \mathrm{j} \right)},...\mathrm{x}_{\mathrm{n}}^{\left( \mathrm{j} \right)} \right) -\mathrm{y}_{\mathrm{j}} \right)}\mathrm{x}_{\mathrm{i}}^{\left( \mathrm{j} \right)} θi=θiαj=1n(fθ(x0(j),x1(j),...xn(j))yj)xi(j)

2.随机梯度下降法(Stochastic Gradient Descent)

随机梯度下降法,其实和批量梯度下降法原理类似,区别在与求梯度时没有用所有的n个样本的数据,而是仅仅选取一个样本j来求梯度。对应的更新公式是:
θ i = θ i − α ( f θ ( x 0 ( j ) , x 1 ( j ) , . . . x n ( j ) ) − y j ) x i ( j ) \mathrm{\theta}_{\mathrm{i}}=\mathrm{\theta}_{\mathrm{i}}-\mathrm{\alpha}\left( f_{\mathrm{\theta}}\left( \mathrm{x}_{0}^{\left( \mathrm{j} \right)},\mathrm{x}_{1}^{\left( \mathrm{j} \right)},...\mathrm{x}_{\mathrm{n}}^{\left( \mathrm{j} \right)} \right) -\mathrm{y}_{\mathrm{j}} \right) \mathrm{x}_{\mathrm{i}}^{\left( \mathrm{j} \right)} θi=θiα(fθ(x0(j),x1(j),...xn(j))yj)xi(j)

随机梯度下降法,和的批量梯度下降法是两个极端,一个采用所有数据来梯度下降,一个用一个样本来梯度下降。

3.小批量梯度下降法(Mini-batch Gradient Descent)

小批量梯度下降法是批量梯度下降法和随机梯度下降法的折衷,也就是对于n个样本,我们采用x个样子来迭代,1<x<n。当然根据样本的数据,可以调整这个x的值。对应的更新公式是:
θ i = θ i − α ∑ j = t t + x − 1 ( h θ ( x 0 ( j ) , x 1 ( j ) , . . . x n ( j ) ) − y j ) x i ( j ) \mathrm{\theta}_{\mathrm{i}}=\mathrm{\theta}_{\mathrm{i}}-\mathrm{\alpha}\sum_{\mathrm{j}=\mathrm{t}}^{\mathrm{t}+\mathrm{x}-1}{\left( \mathrm{h}_{\mathrm{\theta}}\left( \mathrm{x}_{0}^{\left( \mathrm{j} \right)},\mathrm{x}_{1}^{\left( \mathrm{j} \right)},...\mathrm{x}_{\mathrm{n}}^{\left( \mathrm{j} \right)} \right) -\mathrm{y}_{\mathrm{j}} \right)}\mathrm{x}_{\mathrm{i}}^{\left( \mathrm{j} \right)} θi=θiαj=tt+x1(hθ(x0(j),x1(j),...xn(j))yj)xi(j)

小结:显然,三种梯度下降方法主要区别就在于更新参数时使用多少样本,BGD:使用全部样本,SGD:随机挑选一个样本,MBGD:选取部分样本。值得注意的是,虽然SGD一次迭代只用一个样本,导致迭代方向变化很大,不能很快的收敛到局部最优解,但这也大大减少了每一步的计算复杂度。因此对于大规模样本训练用的最多的还是SGD。

总结

梯度下降的局限性

显然,范例中的函数比较简单,在(0,π)取值范围内属于严格凸函数(超过这个定义域就有多个极值了),如果遇到更为复杂的函数,有着多个极值,甚至我们不能写出其显示表达,大多时候无法得到解析解,梯度下降(GD)也很容易陷入局部极值。例如下图,多个极值问题,以及大面积平坦的鞍点(导数接近于0)。

在这里插入图片描述


挖个坑:虽说梯度下降容易陷入局部极值,但在大规模神经网络训练中(高维非凸)却能取得很好的效果,这是为什么呢?

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值