人工神经网络——梯度下降

目录

 

一、为什么需要梯度下降

二、什么是梯度下降

2.1 直观理解梯度下降

2.2 梯度下降的三种形式

2.2.1 批量梯度下降(Batch Gradient Descent,BGD)

2.2.2 随机梯度下降(Stochastic Gradient Desent,SGD)

2.2.3 小批量梯度下降(Mini-Batch Gradient Descent)

2.2.4 注意事项

2.3 训练提前停止

三、梯度下降实例


一、为什么需要梯度下降

       根据《人工神经网络—理解人工神经元和神经网络》可知构建的人工神经网络含有大量参数,包括权重w和阈值b。网络训练过程中,这些参数有无数个取值组合,一个组合对应一个模型,可得到模型的集合—假设空间。训练的目标为从假设空间中选择最佳模型。《人工神经网络-学习策略》介绍了衡量评估训练过程中模型性能的标准以及学习目标—最小化目标函数。

       “最小化函数”,大家的第一反应大概都是“求导啊,计算导数为0的点,然后根据单调性筛选极小值点,最后通过比较所有极小值计算最小值”。很熟悉,高考压轴函数题的一贯做法。但是由于模型参数成千上万,模型函数极其复杂,解析解通常不存在,因此人工计算最小值过于麻烦(当然,也不是不能做,但咱得有为原子弹研究付出贡献的先辈们的脑力、精力和毅力)。那么计算机该如何最小化目标函数呢,梯度下降应运而生。

二、什么是梯度下降

2.1 直观理解梯度下降

       给定关于自变量x的函数f(x),让计算机去计算使得f(x)取得最小值的点x,遍历是不可能的,计算量太大。那么该如何去做:猜,猜大了小一点,猜小了大一点。那么根据啥猜:梯度(导数),极小值邻域内一定先递减再递增,当前导数大于0一定是猜大了,导数小于0一定是猜小了。以f\begin{pmatrix} x \end{pmatrix}=x^{2}为例:

人工神经网络——梯度下降_第1张图片

计算机的目标是找到x=0的点,计算机需要不断猜x,x有三种情况:

(1)猜小了,x位于函数图像左半部分,单调下降,梯度为负;那么下一步猜大一点

(2)猜大了,x位于函数图像右半部分,单调上升,梯度为正;那么下一步猜小一点

(3)猜对了,结束猜测。

(1)(2)两种情况都是根据梯度使得函数值减少,即梯度相反的方向(梯度为负就猜大,梯度为正就猜小),就是所谓梯度下降。

 

       使用下山的例子进行进一步介绍。在一个月黑风高的夜晚,我们位于盆地周围的山坡上,目标是安全到达盆地。那么该如何以最快的方式下山呢?当然是寻找当前位置最陡峭的地方,然后朝着高度下降的方向走。那么大山就对应着我们的目标函数,到达盆地对应着找到函数的最小值,最快的下山方式就是当前位置最为陡峭的方向,也就是函数的梯度下降的方向。使用多变量函数解释为什么梯度下降方向就是最陡峭的方向,使得函数值下降最快的方向:

人工神经网络——梯度下降_第2张图片

2.2 梯度下降的三种形式

假设有N个训练样本\begin{Bmatrix} \begin{pmatrix} x_{1},y_{1} \end{pmatrix},...,\begin{pmatrix} x_{N},y_{N} \end{pmatrix} \end{Bmatrix},训练模型为f\begin{pmatrix} x,\theta \end{pmatrix},每个训练样本的损失函数为L\begin{pmatrix} f\begin{pmatrix} x_{i} \end{pmatrix},y_{i} \end{pmatrix},用于梯度下降计算的风险函数为J\begin{pmatrix} \theta \end{pmatrix}\theta是训练参数。目标为最小化J\begin{pmatrix} \theta \end{pmatrix}

2.2.1 批量梯度下降(Batch Gradient Descent,BGD)

批量梯度下降使用整个训练集上的风险函数计算梯度,每次迭代采集所有训练样本。其迭代公式为:

式中,\alpha为搜索步长,是用来控制每一次搜索的步长(下山每一步的距离)。过大会出现步子错过最低点,甚至爬上了更高的地方;太小会出现下山时间过长,示意图如下。

人工神经网络——梯度下降_第3张图片

2.2.2 随机梯度下降(Stochastic Gradient Desent,SGD)

随机梯度下降是使用单个样本的损失函数计算梯度,每次迭代采集一个样本。

2.2.3 小批量梯度下降(Mini-Batch Gradient Descent)

小批量梯度下降是随机梯度下降和批量梯度下降的的折中形式。它是将训练集分为若干个不交叉的子集,使用子集的风险函数计算梯度,每次迭代采集一个子集的训练数据。迭代公式为:

2.2.4 注意事项

批量梯度下降使用全部数据的风险函数计算梯度,使得最终解为全局最小值,但是存在计算成本高的缺点;

       随机梯度下降使用单个样本的损失函数计算梯度,每次迭代都是朝着局部极小值的方向前进,但是最终解也会在最小值附近。

       小批量梯度下降是目前经常使用的方式,子集数据数目的选择一般为32,64,128,256,…,即2的次方。另外需要考虑自身电脑的计算能力。

2.3 训练提前停止

在实际训练过程中,往往不会在梯度为0的时候停止训练,因为此时的模型对训练数据过度拟合,在测试数据上误差太大。为了防止提前过拟合,往往采用提前停止策略:

(1)达到一定的迭代次数;

(2)训练样本的风险函数值小于阈值;

(3)梯度达到一定阈值;

(4)验证集的错误率小于阈值;

2.4 梯度下降步骤

1、选择梯度下降方式,搜索步长,小批量梯度下降的子集含有数据数目,停止策略;

2、根据梯度下降方式采集数据——随机梯度下降采集一个数据;批量梯度下降采集训练集全部数据;小批量梯度下降采集子集数据(由我们设定)

3、计算采集数据的风险以及对参数的梯度

4、根据梯度更新参数

5、判断是否满足停止策略,满足则退出,否则转为2

三、梯度下降实例

我们产生随机数据拟合函数y = x_{1}+x_{2},拟合模型为f\bigl(\begin{smallmatrix} x_{i} \end{smallmatrix}\bigr)=w_{1}x_{i1}+w_{2}x_{i2}w_{1}w_{2}的理想结果值为1。程序流程如下:

(1)产生N个位于(0,1)区域内的随机数据X=\begin{Bmatrix} \begin{pmatrix} x_{11},x_{12} \end{pmatrix},..., \begin{pmatrix} x_{N1},x_{N2} \end{pmatrix} \end{Bmatrix}y=\begin{Bmatrix} y_{1},...,y_{N}\end{Bmatrix},y_{i}=x_{i1}+x_{i2}+noise

(2)编写拟合模型f\bigl(\begin{smallmatrix} x_{i} \end{smallmatrix}\bigr)=w_{1}x_{i1}+w_{2}x_{i2}

(3)定义训练集的均方误差cost=\frac{1}{2N}\sum_{i=1}^{N}\left \| f\begin{pmatrix} x_i \end{pmatrix}-y_{i} \right \|^{2}

(4)定义梯度\frac{\partial J}{\partial w_{i}}=\frac{1}{N}\sum_{i=1}^{N}\left | f\begin{pmatrix} x_{i}-f_{i} \end{pmatrix} \right |x_{i},J为一次迭代采集数据的代价

(5)使用梯度下降进行训练

# 1、import相关模块
import numpy as np
import matplotlib.pyplot as plt

# 2、加载训练数据
SEED = 2536
rdm = np.random.RandomState(SEED)
x_train = rdm.rand(320,2)
y_train = [[x1+x2+rdm.rand()/10.0-0.05] for (x1,x2) in x_train] # 产生[-0.5,0.5]的噪声,y = x1+x2+噪声

# 3、编写模型 y = X*W
def model(X:np.ndarray,W:np.ndarray):
    return np.dot(X,W)

# 4、定义代价函数和梯度下降方法
# 代价函数,均方差
def cost(X:np.ndarray,y:np.ndarray,W:np.ndarray):
    error = model(X,W)-y
    num = X.shape[0]
    return 1/(2.0*num)*np.sum(np.multiply(error,error))
# 计算梯度
def gradient(X:np.ndarray,y:np.ndarray,W:np.ndarray):
    num = X.shape[0]
    error = model(X,W)-y
    grad = np.zeros(W.shape)
    for i in range(len(W.ravel())):
        term = error*X[:,i]
        grad[i] = term/num
    return grad
# 停止准则
def stop_criterion(type,value,threshold):
    if type == 'STOP_ITER': return value > threshold    # 迭代次数达到阈值
    elif type == 'STOP_COST': return value < threshold  # 训练集代价函数小于阈值
    elif type == 'STOP_GRAD': return value < threshold  # 计算梯度小于阈值

# 梯度下降更新参数
def descent(X,y,W,alpha,batch_size,stop_type,threshold):

    num = X.shape[0] #训练样本数目
    i = 0 # 记录迭代次数
    k = 0 # 记录batch
    costs = [cost(X,y,W)] # 记录训练集代价

    while True:
        grad = gradient(X[k:k+batch_size],y[k:k+batch_size],W)

        i += 1
        k += batch_size
        if k>=num:
            k = 0

        W = W - alpha * grad
        costs.append(cost(X[k:k+batch_size],y[k:k+batch_size],W))

        if i%100 == 0:
            print("The %d training step:"%i)
            print("W is {}".format(W))
            print("cost is {},grad is {}".format(costs[-1],grad))
            print()

        value = None
        if stop_type == 'STOP_ITER': value = i
        elif stop_type == 'STOP_COST': value = costs[-1]
        elif stop_type == 'STOP_GRAD':value = grad
        if stop_criterion(stop_type,value,threshold):
            break

    return W,costs,grad,i-1

# 5、训练
W = rdm.rand(2,1)
alpha = 0.01
batch_size = 1
W,costs,grad,iter = descent(x_train,y_train,W,alpha,batch_size,'STOP_ITER',1500)

# 6、可视化
fig,ax = plt.subplots(figsize=(12,4))
ax.plot(np.arange(len(costs)),costs,'r')
ax.set_xlabel('Iteration')
ax.set_ylabel('Cost')
plt.show()

结果如下:

人工神经网络——梯度下降_第4张图片

人工神经网络——梯度下降_第5张图片

本文使用的数据简单,不能够研究得出步长(学习率)、三种梯度下降方式和小批量梯度下降方法的batch设计对模型训练的影响。如果大家想要进一步了解,建议使用预测房价数据集或者预测是否被大学录取数据集进行进一步研究。

你可能感兴趣的:(神经网络)