zoukankan      html  css  js  c++  java
  • 梯度介绍(详细) 代码实现

    https://blog.csdn.net/u013510838/article/details/79845455

    https://blog.csdn.net/huobumingbai1234/article/details/81274614?depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-21&utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-21

    1 引言
    深度学习训练的基本步骤相信大家都很清楚,本节着重来讲解训练中使用到的激活函数,准确率函数,优化函数都有哪几种,以及它们之间的比较。

    2 激活函数
    根据奥卡姆剃刀法则,神经网络采用的是最简单的线性模型 f(x) = wx+b, 并且线性模型的组合仍然为线性模型。但我们要解决的大部分问题又不仅仅是一个线性问题,因此在线性模型中增加非线性元素就显得尤其重要了。激活函数正是增加非线性的一个重要手段。常见的激活函数有sigmoid relu tanh等

    2.1 sigmoid
    函数表达为

    sigmoid是早期使用较多的激活函数,优点为

    输出值为[0, 1], 符合概率分布
    x靠近0时斜率很大,对应为神经元兴奋区,远离0的区域斜率很小,对应为神经元抑制区
    但其缺点也较为明显

    x稍微远离0, 导数就接近于0了,这样在反向传播优化w时,无论w取何值,梯度都很小,也就无法对w更新给出指导了,这种现象称为梯度弥散,在网络层级较深时尤其明显。
    需要进行指数计算,比较耗时
    2.2 tanh
    函数表达为

    tanh和sigmoid其实很像,只是y的分布以0为中心。其同样存在梯度弥散和计算耗时的问题。

    2.3 relu
    函数表达为

    relu是当前使用最为频繁的激活函数,在几乎所有的CNN网络均使用relu作为激活函数,它解决了sigmoid和tanh的问题,优点为

    x大于0时,导数为1,在反向传播计算梯度时,不存在梯度弥散问题。
    x>0时,y=x, x<0时,y=0, 计算十分简单。
    针对于relu的x<0部分,出现了一些变种函数,比如ELU和PRELU,均是针对x<0分支的改进,和relu大体相似。

    3 损失函数
    损失函数用来衡量预测值和真实值之间的差距,深度学习训练的目的,就是至少在训练集上,损失函数要达到一个较小的值。这个较小的值可以是局部最优解,也可以是全局最优解。但局部最优解往往不止一个,且不一定理想。全局最优解则很难求取,且往往是一个过拟合的结果。损失函数有如下几种。

    3.1 平方差
    L(Y,f(X))=(Y−f(X))2,其中Y为真实值,f(x)为预测值

    描述了真实值和预测值之间的空间距离,线性回归中经常使用,分类问题中一般不使用。

    3.2 交叉熵


    它描述了两个概率分布之间的距离,在分类问题中使用较广。

    TensorFlow支持自定义损失函数,如果对于现成的损失函数不满意,完全可以自己定义一个。

    4 优化方法
    优化方法用来指导如何调整参数w和b,来最有效率地使损失函数达到最小。优化方法最初需要手动设置学习率,来调整参数大小。这种方式比较麻烦,后来慢慢出现了各种自动优化学习率的方法。

    4.1 BGD(batch gradient descent)
    BGD每步迭代中,都需要使用训练集的所有内容来计算梯度和误差,来指导参数的更新。这种方式由于使用了训练集中的所有数据,故能够保证梯度是真实有效不含噪声的,故可以设置一个固定的学习率。但计算量太大。

    4.2 SGD(stochastic gradient descent)
    针对BGD计算量大的改进,随机梯度下降。每次随机抽取一定的样本计算梯度和误差,并更新参数。这种方式计算量不大,但由于采用的是随机样本,故梯度不一定是真实的梯度,带有一定的噪声。随着梯度的下降,我们需要逐渐减小学习率,来让其稳定的落入局部最优解。

    4.3 Momentum
    针对SGD梯度中含有噪声的改进。它将前几次的梯度也参与到本次梯度计算中来,也就是利用梯度之和来指导更新参数。它可以加速学习率,从而减少迭代次数,加快收敛速度。

    4.4 AdaGrad
    可以自动更新学习率,但需要设置一个全局学习率。其学习率的表达式如下

    其中,ϵ为全局学习率,我们需要设置一个固定的值。δ是一个很小的常量,大概在e-7, 主要是为了防止分母为0.gi为第i次迭代时的梯度。可以看到随着梯度累加和的增加,学习率会降低,从而使损失函数稳定落入局部最优解。

    4.5 Adam
    Adaptive Moment Estimation, 自适应矩估计,概率论中矩的定义是,如果一个随机变量服从某个分布,则其一阶矩为其平均值,即E(X)。二阶矩为其平方的平均值,即E(X^2)。Adam根据损失函数梯度的一阶矩估计和二阶矩估计来动态调整学习率。其计算过程如下

    其中,g为迭代运算损失函数梯度的累加和,s为梯度的一阶矩估计,r为梯度的二阶矩估计。ρ1和ρ2为衰减系数,一般ρ1=0.9,ρ2=0.999。δ目的是防止分母为0,一般取e-8。ϵ为用户设置的全局学习率,一般可设为e-4。θ为学习率。

    import math
    import numpy as np
    
    
    x = np.array([(1,1,1),(1,2,1),(2,2,1),(3,1,1),(1,3,1),(2,4,1)])
    y =np.array([6, 8, 9, 8, 10, 13])
    #初始化
    m ,dim = x.shape
    theta = np.zeros(dim) # 参数
    alpha = 0.01 #学习率
    momentum = 0.1 #冲量
    threshold = 0.0001 #停止迭代的损失值阈值
    iterations = 1000 #迭代次数
    error = 0 #初始损失值为0
    
    b1 = 0.9 #初始值
    b2 = 0.999
    e = 0.0000001
    mt = np.zeros(dim)
    vt = np.zeros(dim)
    t = 0
    for i in range(iterations):
        print(i)
        for j in range(m):#第j个样本
            t += 1
            print(x[j])
            #总误差损失平均值
            error = 1 / (2 * m ) * np.dot(
                (np.dot(x, theta) - y ).T,
                (np.dot(x, theta) -y ) )
            if abs(error) <= threshold:
                break
            gradient = x[j] * (np.dot (x[j], theta) - y[j]) #第j个样本的梯度值
            print(gradient)
            mt = b1 * mt + (1 - b1 ) * gradient
            vt = b2 * vt + (1 - b2 ) * (gradient**2)
            mtt = mt / (1- (b1**( t + 1 )))
            #print(mtt)
            vtt = vt / (1-(b2**( t + 1 )))
            vtt_sqrt = np.array([math.sqrt(vtt[0]),
                                 math.sqrt(vtt[1]),
                                 math.sqrt(vtt[2])
                                 ])
            theta = theta - alpha * mtt / (vtt_sqrt + e)
        print('迭代次数:%d' % (i + 1), 'theta:', theta, 'error:%f' % error)
    

      

  • 相关阅读:
    Web开发细节搜集
    excel设置单元格为文本
    网页QQ唤起
    .net提高文章
    代码重构学习
    js的undefined怎么判断
    微软.net一些类的源码
    FineMessBox的js依赖导致错误Uncaught ReferenceError: addEvent is not defined
    [译转]深入理解LayoutInflater.inflate()
    java 和 Android Base64加密
  • 原文地址:https://www.cnblogs.com/zhangbojiangfeng/p/12759411.html
Copyright © 2011-2022 走看看