【机器学习一】梯度下降---Gradient Descent

梯度下降—Gradient Descent

一、梯度

​ 在微积分里面,对多元函数的参数求∂偏导数,把求得的各个参数的偏导数以向量的形式写出来,就是梯度。比如函数f(x,y), 分别对x,y求偏导数,求得的梯度向量就是 ( ∂ f / ∂ x , ∂ f / ∂ y ) T (∂f/∂x, ∂f/∂y)^T (f/x,f/y)T,简称 g r a d f ( x , y ) grad f(x,y) gradf(x,y)或者 ▽ f ( x , y ) ▽f(x,y) f(x,y)。对于在点 ( x 0 , y 0 ) (x_0,y_0) (x0,y0)的具体梯度向量就是 ( ∂ f / ∂ x 0 , ∂ f / ∂ y 0 ) T (∂f/∂x_0, ∂f/∂y_0)^T (f/x0,f/y0)T.或者 ▽ f ( x 0 , y 0 ) ▽f(x0,y0) f(x0,y0),如果是3个参数的向量梯度,就是 ( ∂ f / ∂ x , ∂ f / ∂ y , ∂ f / ∂ z ) T (∂f/∂x, ∂f/∂y,∂f/∂z)^T (f/x,f/yf/z)T,以此类推。

二、梯度下降算法

2.1 主要相关概念

  • 步长(learning rate):也叫学习率,步长决定了在梯度下降迭代的过程中,每一步沿梯度负方向前进的长度。
  • 特征(feature):指的是样本中输入部分
  • 假设函数(hypothesis function):在监督学习中了拟合输入样本,而使用的假设函数,记为 h θ ( x ) h θ ( x ) hθ(x)hθ(x) hθ(x)hθ(x)。比如对于单个特征的m个样本 ( x ( i ) , y ( i ) ) ( i = 1 , 2 , . . . m ) ( x ( i ) , y ( i ) ) ( i = 1 , 2 , . . . m ) (x(i),y(i))(i=1,2,...m)(x(i),y(i))(i=1,2,...m) x(i),y(i)(i=1,2,...m)x(i),y(i)(i=1,2,...m),可以采用拟合函数如下:$ h_θ(x)=θ_0+θ_1x$。
  • 损失函数(loss function):为了评估模型拟合的好坏,通常用损失函数来度量拟合的程度。损失函数极小化,意味着拟合程度最好,对应的模型参数即为最优参数。

2.2 梯度下降的代数算法

  1. 先决条件:确定优化模型的假设函数和损失函数

  2. 算法相关参数初始化:主要是初始化 θ 0 , θ 1 . . . , θ n θ_0,θ_1...,θ_n θ0,θ1...,θn,算法终止距离ε以及步长 α α α。在没有任何先验知识的时候,我们可以将参数按照高斯分布初始化, 将步长初始化为0.01。在调优的时候再优化。

  3. 算法过程:

    1). 确定当前位置的损失函数的梯度,对于 θ i θ_i θi,其梯度表达式如下:

∂ ∂ θ i J ( θ 0 , θ 1 , . . . , θ n ) \frac{\partial}{\partial\theta_i}J(\theta_0,\theta_1,...,\theta_n) θiJ(θ0,θ1,...,θn)

​ 2). 用步长乘以损失函数的梯度,得到当前位置下降的距离,即 α ∂ ∂ θ i J ( θ 0 , θ 1 , . . . , θ n ) α\frac{\partial}{\partial\theta_i}J(\theta_0,\theta_1,...,\theta_n) αθiJ(θ0,θ1,...,θn)

​ 3).确定是否所有的 θ i θ_i θi,梯度下降的距离都小于 ε ε ε,如果小于 ε ε ε则算法终止,当前所有的 θ i ( i = 0 , 1 , . . . n ) θi(i=0,1,...n) θi(i=0,1,...n)即为最终结果。否则进入步骤4.

​ 4). 更新所有的 θ θ θ,对于 θ i θ_i θi,其更新表达式如下。更新完毕后继续转入步骤1.
θ i = θ i − α ∂ ∂ θ i J ( θ 0 , θ 1 . . . , θ n ) θ_i=θ_i−α\frac{\partial}{\partial\theta_i}J(θ_0,θ_1...,θ_n) θi=θiαθiJ(θ0,θ1...,θn)

2.3 梯度下降的矩阵算法

  1. 先决条件:确定优化模型的假设函数和损失函数

  2. 算法相关参数初始化:主要是初始化 θ 0 , θ 1 . . . , θ n θ_0,θ_1...,θ_n θ0,θ1...,θn,算法终止距离ε以及步长 α α α。在没有任何先验知识的时候,我们可以将参数按照高斯分布初始化, 将步长初始化为0.01。在调优的时候再优化。

  3. 算法过程:

    1). 确定当前位置的损失函数的梯度,对于 θ θ θ向量,其梯度表达式如下:

∂ ∂ θ i J ( θ ) \frac{\partial}{\partial\theta_i}J(\theta) θiJ(θ)

​ 2). 用步长乘以损失函数的梯度,得到当前位置下降的距离,即 α ∂ ∂ θ J ( θ ) α\frac{\partial}{\partial\theta}J(\theta) αθJ(θ)

​ 3).确定是否所有的 θ i θ_i θi,梯度下降的距离都小于 ε ε ε,如果小于 ε ε ε则算法终止,当前所有的 θ i ( i = 0 , 1 , . . . n ) θi(i=0,1,...n) θi(i=0,1,...n)即为最终结果。否则进入步骤4.

​ 4). 更新所有的θ,对于θi,其更新表达式如下。更新完毕后继续转入步骤1.
θ = θ − α ∂ ∂ θ J ( θ ) θ = θ−α\frac{\partial}{\partial\theta}J(\theta) θ=θαθJ(θ)
​ 矩阵算法和代数算法的区别在于可以以矩的方式直接计算出梯度

2.4 梯度下降的算法调优

​ 在使用梯度下降的时候,哪些地方可以调优呢?

  1. 算法的学习率:在实际运行中,可以多取一些值运行算法 ,观察损失函数的变化。如果学习率过大,会导致迭代过快,容易产生震荡而得不到最优解;如果学习率过小,会导致迭代过慢,算法很难收敛。在实际中,我们可以使用学习率变化的算法,迭代初期,学习率大一下,后面逐渐减小,这样有利于快速迭代而不会产生震荡。
  2. 算法的初始参数选择:算法的初始值不同,获得的最小值也可能不同;如果一个函数是凸函数,那么获得的局部最优解一定是全局最优解。而如果函数非凸,初值的选择可能会导致最优解为局部最优解
  3. 归一化:由于样本不同特征的取值范围不一样,可能导致迭代速度很慢,为了减少特征取值的影响,可以对特征数据取值归一化,也就是对每一个特征 x x x求出期望 x ˉ \bar{x} xˉ和标准差 s t d ( x ) std(x) std(x)得到:

x − x ˉ s t d ( x ) \frac{x-\bar{x}}{std(x)} std(x)xxˉ

​ 这样特征的新期望值为0,新方差为1,可以加快迭代速度。

三、梯度下降家族

3.1 批量梯度下降法(Batch Gradient Desent,BGD)

​ 批量梯度下降法是梯度下降常用算法,表示在更新梯度参数时使用所有的样本来参与更新。比如我们常见的线性回归梯度更新公式:
θ i = θ i − α ∑ j = 1 m ( h θ ( x 0 j , x 1 j , . . . , x n j ) − y j ) x i j \theta_i = \theta_i-\alpha\sum\limits^{m}_{j=1}(h_\theta(x_0^j,x_1^j,...,x_n^j)-y_j)x_i^j θi=θiαj=1m(hθ(x0j,x1j,...,xnj)yj)xij
​ 这个就是批量梯度下降,因为m个样本都参与了梯度更新

3.2 随机梯度下降法(Stochastic Gradient Descent,SGD)

​ 随机梯度下降法,其实和批量梯度下降法原理类似,区别在与求梯度时没有用所有的m个样本的数据,而是仅仅选取一个样本j来求梯度。对应的线性回归更新公式是:
θ i = θ i − α ( h θ ( x 0 j , x 1 j , . . . , x n j ) − y j ) x i j \theta_i = \theta_i-\alpha(h_\theta(x_0^j,x_1^j,...,x_n^j)-y_j)x_i^j θi=θiα(hθ(x0j,x1j,...,xnj)yj)xij

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

​ 小批量梯度下降法是批量梯度下降法和随机梯度下降法的折衷,也就是对于m个样本,我们采用x个样子来迭代,1<x<m。一般可以取x=10,当然根据样本的数据,可以调整这个x的值。

四、梯度下降法和其他无约束优化算法的比较

​ 在机器学习中的无约束优化算法,除了梯度下降以外,还有前面提到的最小二乘法,此外还有牛顿法和拟牛顿法。

​ 梯度下降法和最小二乘法相比,梯度下降法需要选择步长,而最小二乘法不需要。梯度下降法是迭代求解,最小二乘法是计算解析解。如果样本量不算很大,且存在解析解,最小二乘法比起梯度下降法要有优势,计算速度很快。但是如果样本量很大,用最小二乘法由于需要求一个超级大的逆矩阵,这时就很难或者很慢才能求解解析解了,使用迭代的梯度下降法比较有优势。

​ 梯度下降法和牛顿法/拟牛顿法相比,两者都是迭代求解,不过梯度下降法是梯度求解,而牛顿法/拟牛顿法是用二阶的海森矩阵的逆矩阵或伪逆矩阵求解。相对而言,使用牛顿法/拟牛顿法收敛更快。但是每次迭代的时间比梯度下降法长。

五、手撕梯度下降算法代码

​ 本节我们使用python写出梯度下降代码优化Himmelblau函数:
f ( x , y ) = ( x 2 + y − 11 ) 2 + ( x + y 2 − 7 ) 2 f(x,y) = (x^2+y-11)^2+(x+y^2-7)^2 f(x,y)=(x2+y11)2+(x+y27)2

'''
手写梯度下降算法:更新函数(x[0]**2+x[1]-11)**2+(x[0]+x[1]**2-7)**2
'''
import numpy as np
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

LEARN_RATE = 0.001
STOP_VALUE = 1e-5
listValue =[]


def himmelblau(x):
    '''himmeblau函数'''
    return (x[0]**2+x[1]-11)**2+(x[0]+x[1]**2-7)**2

def derihimme(x):
    '''himme函数导数'''
    y = [2*(x[0]**2+x[1]-11)*(2*x[0])+2*(x[0]+x[1]**2-7),
         2*(x[0]**2+x[1]-11)+2*(x[0]+x[1]**2-7)*(2*x[1])]
    return y

def drawhimme(listV):
    '''画图'''
    x = np.arange(-6.,6.,0.1)
    y = np.arange(-6.,6.,0.1)
    print("x,y range:",x.shape,y.shape)
    #计算
    X,Y = np.meshgrid(x,y)
    Z = himmelblau([X,Y])
    #显示
    fig = plt.figure("himmelblau")
    ax = Axes3D(fig)
    ax.plot_surface(X, Y, Z,
                    rstride=1,  # rstride(row)指定行的跨度
                    cstride=1,  # cstride(column)指定列的跨度
                    cmap=plt.get_cmap('rainbow'))  # 设置颜色映射
    ax.view_init(60,-30)
    ax.set_xlabel('x')
    ax.set_ylabel('y')
    cm = plt.cm.get_cmap('RdYlBu')
    for v in listV:
        ax.scatter(v[0],v[1],himmelblau(v),
                   edgecolors='k',
                   cmap=plt.cm.get_cmap('RdYlBu'),
                   s=10)
    plt.show()

def gradentUpdate(initValue):
    '''梯度更新'''
    y_first = himmelblau(initValue)
    listValue.append(initValue)
    y_gradent = derihimme(initValue)
    valueUpdate = [initValue[0]-y_gradent[0]*LEARN_RATE,
                   initValue[1]-y_gradent[1]*LEARN_RATE]
    y_update = himmelblau(valueUpdate)
    y_abs = np.abs(y_update-y_first)
    for step in range(2000):
        initValue = valueUpdate
        y_first = y_update
        listValue.append(initValue)

        y_gradent = derihimme(initValue)
        valueUpdate = [initValue[0] - y_gradent[0] * LEARN_RATE,
                       initValue[1] - y_gradent[1] * LEARN_RATE]
        y_update = himmelblau(valueUpdate)
        y_abs = np.abs(y_update - y_first)
        if(y_abs<STOP_VALUE):
            break
    return valueUpdate

if  __name__== "__main__":
    initValue0 = [4., 4.]
    initValue1 = [4., -4.]
    initValue2 = [-5., 4.]
    initValue3 = [-5., -5.]
    #不同的初始值对应不同的局部最小值
    print(gradentUpdate(initValue0))
    print(gradentUpdate(initValue1))
    print(gradentUpdate(initValue2))
    print(gradentUpdate(initValue3))
    drawhimme(listValue)
#out:非常接近各不同的解析解
#[2.9985528523044143, 2.0034789022320547]
#[3.584730946678452, -1.8514418324715358]
#[-2.806509818820845, 3.131577669902277]
#[-3.7799833500723787, -3.2842689582740467]

结论:不同的初始值最终优化为不同的局部最小值
在这里插入图片描述

学习参考来自:https://www.cnblogs.com/pinard/p/5970503.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值