精华内容
下载资源
问答
  • 反向传播——通俗易懂

    万次阅读 多人点赞 2018-10-04 12:05:05
    最近在看深度学习的东西,一开始看的吴恩达...反向传播法其实是神经网络的基础了,但是很多人在学的时候总是会遇到一些问题,或者看到大篇的公式觉得好像很难就退缩了,其实不难,就是一个链式求导法则反复用。如果...

    最近在看深度学习的东西,一开始看的吴恩达的UFLDL教程,有中文版就直接看了,后来发现有些地方总是不是很明确,又去看英文版,然后又找了些资料看,才发现,中文版的译者在翻译的时候会对省略的公式推导过程进行补充,但是补充的又是错的,难怪觉得有问题。反向传播法其实是神经网络的基础了,但是很多人在学的时候总是会遇到一些问题,或者看到大篇的公式觉得好像很难就退缩了,其实不难,就是一个链式求导法则反复用。如果不想看公式,可以直接把数值带进去,实际的计算一下,体会一下这个过程之后再来推导公式,这样就会觉得很容易了。

      说到神经网络,大家看到这个图应该不陌生:

     

      这是典型的三层神经网络的基本构成,Layer L1是输入层,Layer L2是隐含层,Layer L3是隐含层,我们现在手里有一堆数据{x1,x2,x3,...,xn},输出也是一堆数据{y1,y2,y3,...,yn},现在要他们在隐含层做某种变换,让你把数据灌进去后得到你期望的输出。如果你希望你的输出和原始输入一样,那么就是最常见的自编码模型(Auto-Encoder)。可能有人会问,为什么要输入输出都一样呢?有什么用啊?其实应用挺广的,在图像识别,文本分类等等都会用到,我会专门再写一篇Auto-Encoder的文章来说明,包括一些变种之类的。如果你的输出和原始输入不一样,那么就是很常见的人工神经网络了,相当于让原始数据通过一个映射来得到我们想要的输出数据,也就是我们今天要讲的话题。

      本文直接举一个例子,带入数值演示反向传播法的过程,公式的推导等到下次写Auto-Encoder的时候再写,其实也很简单,感兴趣的同学可以自己推导下试试:)

      假设,你有这样一个网络层:

      第一层是输入层,包含两个神经元i1,i2,和截距项b1;第二层是隐含层,包含两个神经元h1,h2和截距项b2,第三层是输出o1,o2,每条线上标的wi是层与层之间连接的权重,激活函数我们默认为sigmoid函数。

      现在对他们赋上初值,如下图:

      其中,输入数据  i1=0.05,i2=0.10;

         输出数据 o1=0.01,o2=0.99;

         初始权重  w1=0.15,w2=0.20,w3=0.25,w4=0.30;

               w5=0.40,w6=0.45,w7=0.50,w8=0.55

     

      目标:给出输入数据i1,i2(0.05和0.10),使输出尽可能与原始输出o1,o2(0.01和0.99)接近。

     

      Step 1 前向传播

      1.输入层---->隐含层:

      计算神经元h1的输入加权和:

    神经元h1的输出o1:(此处用到激活函数为sigmoid函数):

     

     

      同理,可计算出神经元h2的输出o2:

      

     

      2.隐含层---->输出层:

      计算输出层神经元o1和o2的值:

      

     

    这样前向传播的过程就结束了,我们得到输出值为[0.75136079 , 0.772928465],与实际值[0.01 , 0.99]相差还很远,现在我们对误差进行反向传播,更新权值,重新计算输出。

     

    Step 2 反向传播

    1.计算总误差

    总误差:(square error)

    但是有两个输出,所以分别计算o1和o2的误差,总误差为两者之和:

     

    2.隐含层---->输出层的权值更新:

    以权重参数w5为例,如果我们想知道w5对整体误差产生了多少影响,可以用整体误差对w5求偏导求出:(链式法则)

    下面的图可以更直观的看清楚误差是怎样反向传播的:

    现在我们来分别计算每个式子的值:

    计算

    计算

    (这一步实际上就是对sigmoid函数求导,比较简单,可以自己推导一下)

     

    计算

    最后三者相乘:

    这样我们就计算出整体误差E(total)对w5的偏导值。

    回过头来再看看上面的公式,我们发现:

    为了表达方便,用来表示输出层的误差:

    因此,整体误差E(total)对w5的偏导公式可以写成:

    如果输出层误差计为负的话,也可以写成:

    最后我们来更新w5的值:

    (其中,是学习速率,这里我们取0.5)

    同理,可更新w6,w7,w8:

     

    3.隐含层---->隐含层的权值更新:

     方法其实与上面说的差不多,但是有个地方需要变一下,在上文计算总误差对w5的偏导时,是从out(o1)---->net(o1)---->w5,但是在隐含层之间的权值更新时,是out(h1)---->net(h1)---->w1,而out(h1)会接受E(o1)和E(o2)两个地方传来的误差,所以这个地方两个都要计算。

     

     

    计算

    先计算

    同理,计算出:

              

    两者相加得到总值:

    再计算

    再计算

    最后,三者相乘:

     为了简化公式,用sigma(h1)表示隐含层单元h1的误差:

    最后,更新w1的权值:

    同理,额可更新w2,w3,w4的权值:

     

      这样误差反向传播法就完成了,最后我们再把更新的权值重新计算,不停地迭代,在这个例子中第一次迭代之后,总误差E(total)由0.298371109下降至0.291027924。迭代10000次后,总误差为0.000035085,输出为[0.015912196,0.984065734](原输入为[0.01,0.99]),证明效果还是不错的。

    展开全文
  • 如图,共两部分,softmax一部分,cross-entropy一部分,a1...正向传播和反向传播基本规则(可以参考cs231n的教程): 正向就是正常运算,没什么说的,正向的多对一操作,求和,正向的一对多,每一条线都传播同样的...

    如图,共两部分,softmax一部分,cross-entropy一部分,a1、a2、a3是输入,y1、y2、y3是softmax的输出,t1、t2、t3是label,图中右侧输出Loss=cross entropy,输入gradient=1。

    正向传播和反向传播基本规则(可以参考cs231n的教程):

    正向就是正常运算,没什么说的,正向的多对一操作,求和,正向的一对多,每一条线都传播同样的值。关于汇聚和分散的原则,正向反向一样。

    反向传播操作:

    加法,grad_c=1,c=a+b,则grad_a=grad_b=grad_c。

    乘法,grad_c=1,c=a×b,则grad_a=grad_c*b和grad_b=grad_c*a。

    log、取导数等,都按正常导数就好了,需要注意反向传播求导过程的一个特点,y = w*x,dy/dw=x,所以想反向传播去更新网络参数w,前向传播过程是需要保留这个x的,x指每一个中间操作(例如图中的exp(a1)、y1、t1logy1等等),不特指输入数据x,所以关于神经网络的内存占用量等计算都少不了这些考量。

    神经网络两大内存占用:前向传播的缓存,网络自身的参数。

     

    参考图:

     

     

    参考实现:

    前向传播的loss并没有直接被后向传播使用,直接使用前边推导出的结果(y-t)作为梯度。。

     

    关于if-else,我刚开始也看蒙了,刚开始我以为ifelse是为了应对脏数据的容错,后来测了一下,代码是跑不通的。
    所以这段代码的意思是,如果size相等,说明你的label是onehot形式的,如果size不相等,说明你的label是index形式的,onehot直接相减就是误差,index实际是按label去取数据,如果一样,取出来就是1,就是误差0(公式里有个-1),如果label不一样,就是误差“2”,为什么,因为这个错误的y没被t指向,所以没减1,且t指向的那个0被减1,所以是-1和+1两个误差,因为这两个误差分属于两个index,也就是两个分类,所以虽然-1++1=0,但是误差不是0,onehot学的是分布。

    demo:

    import numpy as np
    
    a = np.array([
        [0,1,0,0],
        [0,0,0,1],
        [1,0,0,0],
    ])
    t = np.array([
        [0,1,0,0],
        [0,0,1,0],
        [1,0,0,0],
    ])
    t2 = np.array([1,2,0])
    t3 = np.array([1,3,0])
    
    print(a)
    a[np.arange(3),t2] -= 1
    a = a/3
    print(a)
    print(sum(a))

    t是one-hot形式的target,t2、t3代表非one-hot形式的target,t2对应t,a相应的有一个数据不正确,会得到如下结果。

    如果使用t3,结果就是全0。

    [[0 1 0 0]
     [0 0 0 1]
     [1 0 0 0]]
    [[ 0.          0.          0.          0.        ]
     [ 0.          0.         -0.33333333  0.33333333]
     [ 0.          0.          0.          0.        ]]
    [ 0.          0.         -0.33333333  0.33333333]

     

    展开全文
  • 反向传播算法 ​ 然后,代价通过反向算法返回到网络中,调整权重并计算梯度。未完待续…… 分析 ​ 可能是你们在学校里做过用代数的方法来分析反向传播。对于普通函数,这很简单。但当解析法很困难时,我们通常...

    定义

    向前传播

    ​ 通常,当我们使用神经网络时,我们输入某个向量x,然后网络产生一个输出y,这个输入向量通过每一层隐含层,直到输出层。这个方向的流动叫做正向传播。

    ​ 在训练阶段,输入最后可以计算出一个代价标量J(θ)。

    反向传播算法

    ​ 然后,代价通过反向算法返回到网络中,调整权重并计算梯度。未完待续……

    分析

    ​ 可能是你们在学校里做过用代数的方法来分析反向传播。对于普通函数,这很简单。但当解析法很困难时,我们通常尝试数值微分。

    数值微分

    ​ 由于代数操作很困难,在数值方法中,我们通常使用计算量大的方法,因此经常需要用到计算机。一般有两种方法,一种是利用近邻点,另一种是利用曲线拟合。

    随机梯度下降法

    ​ 负责“学习”的算法。它使用了由反向传播算法产生的梯度。

    反向传播算法

    ​ 然后,反向传播算法返回到网络中,调整权重来计算梯度。一般来说,反向传播算法不仅仅适用于多层感知器。它是一个通用的数值微分算法,可以用来找到任何函数的导数,只要给定函数是可微的。

    ​ 该算法最重要的特点之一是,它使用了一个相对简单和廉价的程序来计算微分,提高效率。

    如何计算一个代价函数的梯度

    ​ 给定一个函数f,我们想要找到梯度:

    ​ x是一组我们需要它的导数的变量,y是额外的变量,我们不需要它的导数。

    ​ 为了使网络继续学习,我们想要找到代价函数的梯度。

    损失函数

    ​ 这个函数通常应用于一个数据点,寻找预测点和实际点之间的距离。大多数情况下,这是距离的平方损失。

    代价函数

    ​ 这个函数是所有损失函数的组合,它不总是一个和。但有时是平均值或加权平均值。例如:

    如何计算一个代价函数的梯度

    ​ 给定一个函数f,我们想要找到梯度:

    ​ x是一组我们需要它的导数的变量,y是额外的变量,我们不需要它的导数。

    ​ 为了网络的学习,我们想要找到代价函数的梯度。

    微积分链式法则

    ​ 假设x是实数,f和g都是实数到实数的映射函数。此外,


    ​ 根据链式法则,

    多变量链式法则

    ​ 已知x和y是不同维数的向量,

    ​ g和f也是从一个维度映射到另一个维度的函数,

    ​ 或者说,

    ​ ∂y /∂x是g的n×m雅可比矩阵。

    梯度

    ​ 而导数或微分是沿一个轴的变化率。梯度是一个函数沿多个轴的斜率矢量。

    雅可比矩阵

    ​ 有时我们需要找出输入和输出都是向量的函数的所有偏导数。包含所有这些偏导数的矩阵就是雅可比矩阵。

    ​ 有函数

    ​ 雅可比矩阵J为:

    张量的链式法则

    ​ 我们大部分时间都在处理高维数据,例如图像和视频。所以我们需要将链式法则扩展到张量。

    ​ 想象一个三维张量,

    ​ z值对这个张量的梯度是,

    ​ 对于这个张量, iᵗʰ 指数给出一个向量,

    ​ 所以考虑到这一点,

    ​ 张量的链式法则是,

    概念

    计算图

    ​ 这是一个关于直线方程的计算图的例子。开始节点是你将在方程中看到的,为了计算图的方便,总是需要为中间节点定义额外的变量,在这个例子中是节点u。节点“u”等价于“mx”。

    ​ 我们引入这个概念来说明复杂的计算流程的支撑算法。

    ​ 还记得之前,当我们把损失函数定义为差的平方,这就是我们在计算图的最后一层使用的。其中y是实际值a是预测值。

    ​ 请注意,我们的损失值严重依赖于最后的激活值,而最后的激活值又依赖于前一个激活值,再依赖于前一个激活值,以此类推。

    ​ 在神经网络的前进过程中,我们最终得到一个预测值a。在训练阶段,我们有一个额外的信息,这就是网络应该得到的实际结果,y。我们的损失函数就是这些值之间的距离。当我们想要最小化这个距离时,我们首先要更新最后一层的权重。但这最后一层依赖于它的前一层,因此我们更新它们。所以从这个意义上说,我们是在向后传递神经网络并更新每一层。

    敏感性改变

    ​ 当x的一个小变化导致函数f的一个大变化时,我们说函数对x非常敏感如果x的一个小变化导致f的一个小变化,我们说它不是很敏感。

    ​ 例如,一种药物的有效性可用f来衡量,而x是所使用的剂量。灵敏度表示为:

    ​ 为了进一步扩展,我们假设现在的函数是多变量的。

    ​ 函数f可以对每个输入有不同的敏感度。举个例子,也许仅仅进行数量分析是不够的,所以我们把药物分解成3种活性成分,然后考虑每种成分的剂量。

    ​ 最后一点扩展,如果其中一个输入值,比如x也依赖于它自己的输入。我们可以用链式法则来找出敏感性。同样的例子,也许x被分解成它在身体里的组成部分,所以我们也要考虑这个。

    ​ 我们考虑x的组成,以及它的成分如何影响药物的整体效果。

    ​ 在这里,我们测量的是整个药物的效果对药物中这个小成分的敏感度。

    一个简单的模型

    ​ 这个计算图考虑了节点a和它前面的节点a '之间的连接。

    ​ 用链式法则,

    ​ 它测量了a对u的微小变化有多敏感。然后我们继续前面的3次计算,

    ​ 测量u对以下每一项的微小变化的敏感度:

    • 权重,w

    • 之前的激活值,a ’

    • 偏质,b

    ​ 把这些放在一起,

    简单模型的复杂性

    ​ 如果在前面的例子中,我们有两个节点和它们之间的一个链接。在这个例子中,我们有3个节点和2个链接。

    ​ 因为链式法则的链式长度是没有限制的。我们可以对任意数量的层继续这样做。对于这一层,注意计算图是这样的,

    ​ 请注意,需要用附加的刻度对每个节点进行注释。这些刻度不是衍生物,它们只是表示u和u '是不同的、唯一的值或对象

    复杂模型的复杂性

    ​ 到目前为止的例子都是线性的,链表式的神经网络。把它扩展到现实的网络是这样的,

    ​ 我们需要给网络添加一些额外的符号。

    ​ 让我们通过 a¹₁计算一下计算图 a²₁。

    ​ 实际上你会发现两个计算图有一个很大的共同点,特别是到a¹₁。这意味着,如果一个计算已经被计算过,那么它可以在下一次和下下次被重用,依此类推。虽然这增加了内存的占用,但它显著减少了计算时间,而且对于大型神经网络来说,这是必要的。

    ​ 如果我们用链式法则,得到的公式几乎是一样的,只是增加了索引。

    复杂模型的进一步复杂化

    ​ 你会发现一个a²₂ 会有几个路径输出层节点,。

    ​ 所以我们需要对前一层求和。我们从所有前面的节点和它们的梯度的总和中得到的这个值有更新它的指令,以便我们最小化损失。

    最小化成本函数

    ​ 如果你还记得定义6和7,特别是定义7,你会记得成本函数在概念上是预测产出和实际产出之差的平均值或加权平均值。

    ​ 如果我们使用线性回归或逻辑回归的梯度下降算法来最小化代价函数。

    ​ 对于神经网络,我们使用反向传播算法。我想现在已经很清楚为什么我们不能对神经网络使用单一方程了。神经网络并不是我们可以很好地求导数的连续函数。相反,它们近似一个函数的离散节点。因此需要一个递归算法来找到它的导数或梯度,这需要考虑到所有的节点。

    ​ 完整的成本函数是这样的:

    ​ 从概念上讲

    符号对符号导数

    ​ 到目前为止,您已经了解了如何得到神经网络中节点梯度的代数表达式。通过链式法则在张量上的应用和计算图的概念。

    ​ 代数表达式或计算图不处理具体问题,而只是给我们的理论背景,以验证我们正在正确地计算它们。它们帮助指导我们的编码。

    ​ 在下一个概念中,我们将讨论符号对数值导数的影响。

    符号-数值导数

    ​ 这里我们开始脱离理论,进入实践领域。

    算法

    基本设置+计算节点的梯度

    ​ 首先我们要做一些设置,包括神经网络的顺序以及与网络相关的节点的计算图。我们把它们排列好。

    ​ 每个节点u^{(n)} 都与一个操作f^{(i)}相关联,使得:

    ​ 在𝔸^ {(i)}是所有节点的集合,u^ {(n)}的父节点。

    ​ 首先我们需要计算所有的输入节点,为此我们需要将所有的训练数据以x向量的形式输入:

    for i = 1, ...., n_i
    	u_i = get_u(x_i)
    

    ​ 注意,n_i为输入节点数,其中输入节点为:

    ​ 如果这些是输入节点,则节点:

    ​ 是输入节点之后最后一个节点之前的节点u^{(n)}。

    for i = n_i+1, ..., n
    	A_i = { u_j = get_j(Pa(u_i)) }
    	u_i = fi(A_i)
    

    ​ 你会注意到,这和我们链式法则计算图的概念上的方向是相反的。这是因为这部分详细说明了正向传播。

    ​ 我们称这个图为:

    ​ 利用这个图,我们可以构造另一个图:

    ​ G中的每个节点计算正向图节点u^i,而B中的每个节点使用链式法则计算梯度。

    ​ 如果你考虑神经网络中的所有节点和连接它们的边,你就能想到反向传播所需的计算量随着边的数量线性增加。因为每条边都代表了一条链规则的计算,它将一些节点连接到它的一个父节点。

    附加约束+简单的反向传播

    ​ 如前所述,该算法的计算复杂度与网络的边数呈线性关系。但这是假设求每条边的偏导数需要一个常数时间。

    ​ 在这里,我们的目标是建立一个具体反向传播算法。

    Run forward propagation
    

    ​ 这将获得处于随机的或非有用状态的网络的激活值。

    Initialize grad_table
    

    ​ 在这个数据结构中,我们将存储所有我们计算的梯度。

    To get an individual entry, we use grad_table(u_i)
    

    ​ 这将存储计算值:

    grad_table[u_n] = 1
    

    ​ 这将最后一个节点设置为1。

    for j = n-1 to 1
    	grad_table[u_j] = \\sum grad_table[u_i] du_i/du_j
    

    ​ 理论上是这样的:

    return grad_table
    

    ​ 反向传播算法只访问每个节点一次来计算偏置,这避免了不必要的重新计算子表达式的步骤。请记住,这是以更多内存占用为代价的。

    作者:Tojo Batsuuri

    deephub翻译组:孟翔杰

    展开全文
  • 反向传播是训练神经网络的最常用方法之一。Rumelhart、Hinton和Williams(1986)引入了反向传播,该方法到今天仍然很流行。程序员经常使用反向传播训练深层神经网络,因为在图形处理单元上运行时,它的伸缩性很好。...

    反向传播是训练神经网络的最常用方法之一。Rumelhart、Hinton和Williams(1986)引入了反向传播,该方法到今天仍然很流行。程序员经常使用反向传播训练深层神经网络,因为在图形处理单元上运行时,它的伸缩性很好。要了解这种用于神经网络的算法,我们必须探讨如何训练它,以及它如何处理模式。

    经典的反向传播已得到扩展和修改,产生了许多不同的训练算法。本章中将讨论神经网络最常用的训练算法。我们从经典的反向传播开始,然后以随机梯度下降结束本章。

    6.1 理解梯度

    反向传播是梯度下降的一种,许多教科书中通常互换使用这两个术语。梯度下降是指针对每个训练元素,在神经网络中的每个权重上计算一个梯度。由于神经网络不会输出训练元素的期望值,因此每个权重的梯度将为你提示如何修改权重以实现期望输出。如果神经网络确实输出了预期的结果,则每个权重的梯度将为0,这表明无需修改权重。

    梯度是权重当前值下误差函数的导数。误差函数用于测量神经网络输出与预期输出的差距。实际上,我们可以使用梯度下降,在该过程中,每个权重的梯度可以让误差函数达到更低值。

    梯度实质上是误差函数对神经网络中每个权重的偏导数。每个权重都有一个梯度,即误差函数的斜率。权重是两个神经元之间的连接。计算误差函数的梯度可以确定训练算法应增加,还是减小权重。反过来,这种确定将减小神经网络的误差。误差是神经网络的预期输出和实际输出之间的差异。许多不同的名为“传播训练算法”的训练算法都利用了梯度。总的来说,梯度告诉神经网络以下信息:

    • 零梯度——权重不会导致神经网络的误差;
    • 负梯度——应该增加权重以减小误差;
    • 正梯度——应当减小权重以减小误差。

    由于许多算法都依赖于梯度计算,因此我们从分析这个过程开始。

     6.1.1 什么是梯度

    首先,让我们探讨一下梯度。本质上,训练是对权重集的搜索,这将使神经网络对于训练集具有最小的误差。如果我们拥有无限的计算资源,那么只需尝试各种可能的权重组合,来确定在训练期间提供最小误差的权重。

    因为我们没有无限的计算资源,所以必须使用某种快捷方式,以避免需要检查每种可能的权重组合。这些训练算法利用了巧妙的技术,从而避免对所有权重进行蛮力搜索。但这种类型的穷举搜索将是不可能的,因为即使小型网络也具有无限数量的权重组合。

    请考虑一幅图像,它展示每个可能权重的神经网络误差。图6-1展示了单个权重的误差。

     

    图6-1 单个权重的误差

    从图6-1中很容易看到,最佳权重是曲线的

     

    (

     

    )值最低的位置。问题是我们只看到当前权重的误差;我们看不到整幅图像,因为该过程需要穷尽的搜索。但是,我们可以确定特定权重下误差曲线的斜率。在图6-1中,我们看到误差曲线在

     

    =1.5处的斜率。与误差曲线相切(在

     

    =1.5处)的直线给出了斜率。在这个例子中,斜率或梯度为−0.562 2。负斜率表示增大权重会降低误差。

    梯度是指在特定权重下误差函数的瞬时斜率。误差曲线在该点的导数给出了梯度。这条线的倾斜程度告诉我们特定权重下误差函数的陡峭程度。

    导数是微积分中最基本的概念之一。对于本书,你只需要了解导数在特定点处提供函数的斜率即可。训练技巧和该斜率可以为你提供信息,用于调整权重,从而降低误差。现在,利用梯度的实用定义,我们将展示如何计算它。

     6.1.2 计算梯度

    我们将为每个权重单独计算一个梯度。我们不仅关注方程,也关注梯度在具有真实数值的实际神经网络中的应用。图6-2展示了我们将使用的神经网络——XOR神经网络。

     

    图6-2 XOR神经网络

    此外,本书线上资源(见引言)的几个示例中使用了相同的神经网络。在本章中,我们将展示一些计算,说明神经网络的训练。我们必须使用相同的起始权重,让这些计算保持一致。但是,上述权重没有什么特征,是由该程序随机生成的。

    前面提到的神经网络是典型的三层前馈神经网络,就像我们之前研究的那样,圆圈表示神经元,连接圆圈的线表示权重,连接线中间的矩形给出每个连接的权重。

    我们现在面临的问题是,计算神经网络中每个权重的偏导数。当一个方程具有多个变量时,我们使用偏导数。每个权重均被视为变量,因为这些权重将随着神经网络的变化而独立变化。每个权重的偏导数仅显示每个权重对误差函数的独立影响。该偏导数就是梯度。

    可以用微积分的链式规则来计算每个偏导数。我们从一个训练集元素开始。对于图6-2,我们提供[1,0]作为输入,并期望输出是1。你可以看到我们将输入应用于图6-2。第一个输入神经元的输入为1.0,第二个输入神经元的输入为0.0。

    该输入通过神经网络馈送,并最终产生输出。第4章“前馈神经网络”介绍了计算输出与总和的确切过程。反向传播既有前向,也有反向。计算神经网络的输出时,就会发生前向传播。我们仅针对训练集中的这个数据项计算梯度,训练集中的其他数据项将具有不同的梯度。在后文,我们将讨论如何结合各个训练集元素的梯度。

    现在我们准备计算梯度。下面总结了计算每个权重的梯度的步骤:

    • 根据训练集的理想值计算误差;
    • 计算输出节点(神经元)的增量;
    • 计算内部神经元节点的增量;
    • 计算单个梯度。

    我们将在随后的内容中讨论这些步骤。

    6.2 计算输出节点增量

    为神经网络中的每个节点(神经元)计算一个常数值。我们将从输出节点开始,然后逐步通过神经网络反向传播。“反向传播”一词就来自这个过程。我们最初计算输出神经元的误差,然后通过神经网络向后传播这些误差。

    节点增量是我们将为每个节点计算的值。层增量也描述了该值,因为我们可以一次计算一层的增量。在计算输出节点或内部节点时,确定节点增量的方法可能会有所不同。首先计算输出节点,并考虑神经网络的误差函数。在本书中,我们将研究二次误差函数和交叉熵误差函数。

     6.2.1 二次误差函数

    神经网络的程序员经常使用二次误差函数。实际上,你可以在网络上找到许多使用二次误差函数的示例。如果你正在阅读一个示例程序,但未提及具体的误差函数,那么该程序可能使用了二次误差函数,也称为MSE函数,我们在第5章“训练和评估”中讨论过。公式6-1展示了MSE函数:

     

    (6-1)

    公式6-1将神经网络的实际输出(

     

    )与预期输出(

     

    )进行了比较。变量

     

    为训练元素的数量乘以输出神经元的数量。MSE将多个输出神经元处理为单个输出神经元的情况。公式6-2展示了使用二次误差函数的节点增量:

     

    (6-2)

    二次误差函数非常简单,因为它取了神经网络的预期输出与实际输出之间的差。

     

    ′表示激活函数的导数。

     6.2.2 交叉熵误差函数

    二次误差函数有时可能需要很长时间才能正确调整权重。公式6-3展示了交叉熵误差(Cross-entropy Error,CE)函数:

     

    (6-3)

    如公式6-4所示,采用交叉熵误差函数的节点增量计算要比采用MSE函数简单得多。

     

    (6-4)

    交叉熵误差函数通常会比二次误差函数结果更好,因为二次误差函数会为误差创建一个陡峭的梯度。我们推荐采用交叉熵误差函数。

    6.3 计算剩余节点增量

    既然已经根据适当的误差函数计算了输出节点的增量,我们就可以计算内部节点的增量,如公式6-5所示:

     

    (6-5)

    我们将为所有隐藏和无偏置神经元计算节点增量,但无须为输入和偏置神经元计算节点增量。即使我们可以使用公式6-5轻松计算输入和偏置神经元的节点增量,梯度计算也不需要这些值。你很快会看到,权重的梯度计算仅考虑权重所连接的神经元。偏置和输入神经元只是连接的起点,它们从来不是终点。

    如果你希望看到梯度计算过程,有几个JavaScript示例显示了这些计算过程。这些示例可以在以下URL中找到:

    http://www.heatonresearch.com/aifh/vol3/

    6.4 激活函数的导数

    反向传播过程需要激活函数的导数,它们通常确定反向传播过程将如何执行。大多数现代深度神经网络都使用线性、Softmax和ReLU激活函数。我们还会探讨S型和双曲正切激活函数的导数,以便理解ReLU激活函数为何表现如此出色。

     6.4.1 线性激活函数的导数

    线性激活函数被认为不是激活函数,因为它只是返回给定的任何值。因此,线性激活函数有时称为一致激活函数。该激活函数的导数为1,如公式6-6所示:

     

    (6-6)

    如前文所述,希腊字母

     

    表示激活函数,在

     

    右上方的撇号表示我们正在使用激活函数的导数。这是导数的几种数学表示形式之一。

     6.4.2 Softmax激活函数的导数

    在本书中,Softmax激活函数和线性激活函数仅在神经网络的输出层上使用。如第1章“神经网络基础”所述,Softmax激活函数与其他激活函数的不同之处在于,其值还取决于其他输出神经元,而不仅仅取决于当前正在计算的输出神经元。方便起见,公式6-7再次展示了Softmax激活函数:

     

    (6-7)

     

    向量代表所有输出神经元的输出。公式6-8展示了该激活函数的导数:

     

    (6-8)

    对于上述导数,我们使用了稍微不同的符号。带有草书风格的符号的比率表示偏导数,当你对具有多个变量的方程进行微分时会使用这个符号。要取偏导数,可以将方程对一个变量微分,而将所有其他变量保持不变。上部的指出要微分的函数。在这个例子中,要微分的函数是激活函数

     

    。下部的表示偏导数的分别微分。在这个例子中,我们正在计算神经元的输出,所有其他变量均视为常量。微分是瞬时变化率:一次只有一个变量能变化。

    如果使用交叉熵误差函数,就不会使用线性或Softmax激活函数的导数来计算神经网络的梯度。通常你只在神经网络的输出层使用线性和Softmax激活函数。因此,我们无须担心它们对于内部节点的导数。对于使用交叉熵误差函数的输出节点,线性和Softmax激活函数的导数始终为1。因此,你几乎不会对内部节点使用线性或Softmax激活函数的导数。

     6.4.3 S型激活函数的导数

    公式6-9展示了S型激活函数的导数:

     

    (6-9)

    机器学习经常利用公式6-9中表示的S型激活函数。我们通过对S型函数的导数进行代数运算来导出该公式,以便在其自身的导数计算中使用S型激活函数。为了提高计算效率,上述激活函数中的希腊字母

     

    表示S型激活函数。在前馈过程中,我们计算了S型激活函数的值。保留S型激活函数的值使S型激活函数的导数易于计算。如果你对如何得到公式6-9感兴趣,可以参考以下网址:

    http://www.heatonresearch.com/aifh/vol3/deriv_sigmoid.html

     6.4.4 双曲正切激活函数的导数

    公式6-10给出了双曲正切激活函数的导数:

     

    (6-10)

    在本书中,我们建议使用双曲正切激活函数,而不是S型激活函数。

     6.4.5 ReLU激活函数的导数

    公式6-11展示了ReLU激活函数的导数:

     

    (6-11)

    严格来说,ReLU激活函数在0处没有导数,但是,由于约定,当

     

    为0时,0处的梯度被替换。具有S型和双曲正切激活函数的深层神经网络可能难以通过反向传播进行训练。造成这一困难的因素很多,梯度消失问题是最常见的原因之一。图6-3展示了双曲正切激活函数及其梯度/导数。

     

    图6-3 双曲正切激活函数及其梯度/导数

    图6-3表明,当双曲正切激活函数(实线)接近−1和1时,双曲正切激活(虚线)的导数消失为0。S型和双曲正切激活函数都有这个问题,但ReLU激活函数没有。图6-4展示了S型激活函数及其消失的导数。

     

    图6-4 S型激活函数及其消失的导数

    6.5 应用反向传播

    反向传播是一种简单的训练算法,可以利用计算出的梯度来调整神经网络的权重。该方法是梯度下降的一种形式,因为我们将梯度降到较低的值。随着程序调整这些权重,神经网络将产生更理想的输出。神经网络的整体误差应随着训练而下降。在探讨反向传播权重的更新过程之前,我们必须先探讨更新权重的两种不同方式。

     6.5.1 批量训练和在线训练

    我们已经展示了如何为单个训练集元素计算梯度。在本章的前面,我们对神经网络输入[1,0]并期望输出1的情况计算了梯度。对于单个训练集元素,这个结果是可以接受的,但是,大多数训练集都有很多元素。因此,我们可以通过两种方式来处理多个训练集元素,即在线训练和批量训练。

    在线训练意味着你需要在每个训练集元素之后修改权重。利用在第一个训练集元素中获得的梯度,你可以计算权重并对它们进行更改。训练进行到下一个训练集元素时,也会计算并更新神经网络。训练将继续进行,直到你用完每个训练集元素为止。至此,训练的一个迭代或一轮(epoch)已经完成。

    批量训练也利用了所有训练集元素,但是,我们不着急更新所有权重。作为替代,我们对每个训练集元素的梯度求和。一旦我们完成了对训练集元素梯度的求和,就可以更新神经网络权重。至此,迭代完成。

    有时,我们可以设置批量的大小。如你的训练集可能有10 000个元素,此时可选择每1 000个元素更新一次神经网络的权重,从而使神经网络权重在训练迭代期间更新10次。

    在线训练是反向传播的最初方式。如果要查看该程序批处理版本的计算,请参考以下在线示例:

    http://www.heatonresearch.com/aifh/vol3/xor_batch.html

     6.5.2 随机梯度下降

    批量训练和在线训练不是反向传播的仅有选择。随机梯度下降(SGD)是反向传播算法中最受欢迎的算法。SGD可以用批量或在线训练模式工作。在线SGD简单地随机选择训练集元素,然后计算梯度并执行权重更新。该过程一直持续到误差达到可接受的水平为止。与每次迭代遍历整个训练集相比,选择随机训练集元素通常会更快收敛到可接受的权重。

    批量SGD可通过选择批量大小来实现。对于每次迭代,随机选择数量不应超过所选批量大小的训练集元素,因此选择小批量。更新时像常规反向传播批量处理更新一样,将小批量处理中的梯度相加。这种更新与常规批量处理更新非常相似,不同之处在于,每次需要批量时都会随机选择小批量。迭代通常以SGD处理单个批量。批量大小通常比整个训练集小得多。批量大小的常见选择是600。

     6.5.3 反向传播权重更新

    现在,我们准备更新权重。如前所述,我们将权重和梯度视为一维数组。给定这两个数组,我们准备为反向传播训练的迭代计算权重更新。公式6-12给出了为反向传播更新权重的公式:

     

    (6-12)

    公式6-12计算权重数组中每个元素的权重变化。你也会注意到,公式6-12要求对来自上一次迭代的权重进行改变。你必须将这些值保存在另一个数组中。如前所述,权重更新的方向与梯度的符号相反:正梯度会导致权重减小,反之负梯度会导致权重增大。由于这种相反关系,公式6-12以负号开始。

    公式6-12将权重增量计算为梯度与学习率(以ε表示)的乘积。此外,我们将之前的权重变化与动量值(以α表示)的乘积相加。学习率和动量是我们必须提供给反向传播算法的两个参数。选择学习率和动量的值对训练的表现非常重要。不幸的是,确定学习率和动量主要是通过反复试验实现的。

    学习率对梯度进行缩放,可能减慢或加快学习速度。低于1.0的学习率会减慢学习速度。如学习率为0.5会使每个梯度减少50%;高于1.0的学习率将加速训练。实际上,学习率几乎总是低于1。

    选择过高的学习率会导致你的神经网络无法收敛,并且会产生较高的全局误差,而不会收敛到较低值。选择过低的学习率将导致神经网络花费大量时间实现收敛。

    和学习率一样,动量也是一个缩放因子。尽管是可选的,但动量确定了上一次迭代的权重变化中有百分之多少应该应用于这次迭代。如果你不想使用动量,只需将它的值指定为0。

    动量是用于反向传播的一项技术,可帮助训练逃避局部最小值,这些最小值是误差图上的低点所标识的值,而不是真正的全局最小值。反向传播倾向于找到局部最小值,而不能再次跳出来。这个过程导致训练收敛误差较高,这不是我们期望的。动量可在神经网络当前变化的方向上对它施加一些力,让它突破局部最小值。

     6.5.4 选择学习率和动量

    动量和学习率有助于训练的成功,但实际上它们并不是神经网络的一部分。一旦训练完成,训练后的权重将保持不变,不再使用动量或学习率。它们本质上是一种临时的“脚手架”,用于创建训练好的神经网络。选择正确的动量和学习率会影响训练的效果。

    学习率会影响神经网络训练的速度,降低学习率会使训练更加细致。较高的学习率可能会跳过最佳权重设置,较低的学习率总是会产生更好的结果,但是,降低训练速度会大大增加运行时间。在神经网络训练中降低学习率可能是一种有效的技术。

    你可以用动量来对抗局部最小值。如果你发现神经网络停滞不前,则较高的动量值可能会使训练超出其遇到的局部最小值。归根结底,为动量和学习率选择好的值是一个反复试验的过程。你可以根据训练的进度进行调整。动量通常设置为0.9,学习率通常设置为0.1或更低。

     6.5.5 Nesterov动量

    由于小批量引入的随机性,SGD算法有时可能产生错误的结果。权重可能会在一次迭代中获得非常有益的更新,但是训练元素的选择不当会使其在下一个小批量中被撤销。因此,动量是一种资源丰富的工具,可以减轻这种不稳定的训练结果。

    Nesterov动量是Yu Nesterov在1983年发明的一种较新的技术应用,该技术在他的Introductory Lectures on Convex Optimization: A Basic Course一书中得到了更新[1]。有时将该技术称为Nesterov的加速梯度下降。尽管对Nesterov动量的完整数学解释超出了本书的范围,但我们将针对权重进行详细介绍,以便你可以实现它。本书的示例(包括在线JavaScript的示例)包含Nesterov动量的实现。此外,本书的线上资源包含一些针对Nesterov动量权重更新的JavaScript示例程序。

    公式6-13基于学习率(ε)和动量(α)计算部分权重更新:

     

    (6-13)

    当前迭代用

     

    表示,前一次迭代用

     

    −1表示。这种部分权重更新称为

     

    ,最初从0开始。部分权重更新的后续计算基于部分权重更新的先前值。公式6-13中的偏导数是当前权重下误差函数的梯度。公式6-14展示了Nesterov动量更新,它代替了公式6-12中展示的标准反向传播权重更新:

     

    (6-14)

    上面的权重更新的计算,是部分权重更新的放大。公式6-14中显示增量权重已添加到当前权重中。具有Nesterov动量的SGD是深度学习最有效的训练算法之一。

    6.6 本章小结

    本章介绍了经典的反向传播和SGD。这些方法都基于梯度下降。换言之,它们用导数优化了单个权重。对于给定的权重,导数向程序提供误差函数的斜率。斜率允许程序确定如何更新权重。每个训练算法对斜率或梯度的解释不同。

    尽管反向传播是最古老的训练算法之一,但它仍然是最受欢迎的算法之一。反向传播就是将梯度添加到权重中,负梯度将增大权重,正梯度将减小权重。我们通过学习率来缩放权重,防止权重变化过快。0.5的学习率意味着将权重增加一半的梯度,而2.0的学习率意味着将权重增加2倍的梯度。

    反向传播算法有多种变体,其中一些变体(如弹性传播)颇受欢迎。第7章将介绍一些反向传播的变体。尽管了解这些变体很有用,但是SGD仍然是最常见的深度学习训练算法之一。

    本文摘自《人工智能算法(卷3):深度学习和神经网络》

     

    本书是介绍AI的系列图书中的卷3。AI是一个涵盖许多子学科的、研究广泛的领域。对没有读过本系列图书卷1或卷2的读者,本书简介将提供一些背景信息。读者无须在阅读本书之前先阅读卷1或卷2。下文介绍了可从卷1和卷2中获取的信息。

    自人工智能的早期阶段以来,神经网络就扮演着至关重要的角色。现在,令人兴奋的新技术,例如深度学习和卷积,正在将神经网络带向一个全新的方向。本书结合各种现实世界任务中的神经网络应用,例如图像识别和数据科学,介绍了当前的神经网络技术,包括ReLU激活、随机梯度下降、交叉熵、正则化、Dropout和可视化。

    本书的目标读者是那些对人工智能感兴趣,但苦于没有良好的数学基础的人。读者只需要对大学代数课程有基本了解即可。本书为读者提供配套的示例程序代码,目前已有Java、C#和Python版本。

    展开全文
  • 反向传播算法,经常简称为backprop,允许来自代价函数的信息通过网络向后流动,以便计算梯度。 计算梯度的解析表达式是很直观的,但是数值化地求解这样的表达式在计算上的代价可能很大。反向...
  • 反向传播算法

    千次阅读 2019-09-17 14:54:49
    反向传播(英语:Backpropagation,缩写为BP)是“误差反向传播”的简称,是一种与最优化方法(如梯度下降法)结合使用的,用来训练人工神经网络的常见方法。该方法计算对网络中所有权重计算损失函数的梯度。这个...
  • 什么是反向传播

    千次阅读 2019-10-01 04:25:45
    什么是反向传播 作者:韩小雨 类别:①反向传播算法 ②反向传播模型 反向传播算法(英:Backpropagation algorithm,简称:BP算法) 算法简介:是一种监督学习算法,常被用来训练多层感知机。 于1974年,Paul ...
  • 定义 首先来一个反向传播算法的定义(转自维基百科):反向传播(英语:Backpropagation,缩写为BP)是“误差反向传播”的简称,是一种与最优化方法(如梯度下降法)结合使用的,用来训练人工神经网络的常见方法。...
  • 反向传播算法 BackPropagation ,简称BP算法。常用于训练多层神经网络,那么它到底传播了个啥?又是怎么传播的呢? 我们知道,对于一个机器学习算法,其最终预测出的值与实际值一般会存在差异,那么我们定义这个差异...
  • 本文重点对多层网络的反向传播算法进行介绍,主要记录了四个问题:1、可微阈值单元;2、反向传播算法推导;3.两层sigmoid单元网络训练算法的表示;4.任意深度层次有向无环网络训练算法的表示。
  • 神经网络反向传播算法的简单推导手稿,以便日后查阅使用。这篇文章反向传播算法推导写的非常好,一步一步推导计算反向传播,非常值得阅读。
  • 如何理解反向传播算法

    千次阅读 2018-08-25 10:07:23
    如何理解反向传播算法 如何理解反向传播算法 神经网络模型的数学表示 对代价函数的基本假设 反向传播算法 反向传播的直观理解 总结 参考文献 对于一个算法或者模型的理解可以分为直观理解,算法理解和数学...
  • 反向传播思想及其优缺点

    千次阅读 2018-03-20 15:14:10
    反向传播思想:计算出输出与标签间的损失函数值,然后计算其相对于每个神经元的梯度,根据梯度方向更新权值。(1)将训练集数据输入到ANN的输入层,经过隐藏层,最后达到输出层并输出结果,这是ANN的前向传播过程;...
  • RNN反向传播公式推导

    千次阅读 2018-03-13 18:34:01
    注意⚠️此处与T时刻不同的地方在于,中间时刻是有两个部分反向传播回传误差,T时刻作为最后一项是没有后继节点的,因此只有y一项回传误差项。T时刻可以说是一个特例情况。 更新weight: 输出层: 输入层: 循环层...
  • CNN详解——反向传播过程

    千次阅读 2018-05-30 16:56:23
    CNN的反向传播过程,从原理上讲,与普通的反向传播相同(都使用了链式法则),从具体形式上讲,CNN的反向传播公式又比较特殊,这是因为CNN独有的4个特点: 局部感知:卷积核和图像卷积时,每次卷积核所覆盖的像素...
  • 先看下面信号流图,L=2和M0=M1=M2=M3=3的情况,上面是前向通过,下面部分是反向通过。 1.初始化。假设没有先验知识可用,可以以一个一致分布来随机的挑选突触权值和阈值,这个分布选择为均值等于0的均匀分布,它...
  • 误差反向传播算法浅解

    万次阅读 2017-09-28 09:24:48
    反向传播(英语:Backpropagation,缩写为BP)是“误差反向传播”的简称。由于多层前馈神经网络的训练经常采用误差反向传播算法,人们也常把多层前馈神经网络称为BP网络。
  • 理解深度学习中的反向传播概述介绍图示计算过程图示求导两种模式计算结果重要性 概述 反向传播主要广泛应用于深度学习中的优化器,是优化器的主要工作原理 介绍 反向传播是使训练深度模型在计算上易于处理的关键算法...
  • https://zhuanlan.zhihu.com/p/25081671 详解反向传播算法(上)
  • 反向传播的详细推导和理解
  • 误差反向传播例子

    千次阅读 2019-04-27 21:33:26
    反向传播(Backpropagation)是训练神经网络最通用的方法之一,网上有许多文章尝试解释反向传播是如何工作的,但是很少有包括真实数字的例子,这篇博文尝试通过离散的数据解释它是怎样工作的。 P...
  • 是谁在耳边,说“信号正向传播,误差反向传播” ? 梦回遥远大三的计算智能课,三年前我可想不到居然有朝一日会重新"预习"它...... 每一堂课、一本书,当时只道是寻常,如今不经意想起,忽怀念这些瞬间。所谓成长...
  • 深度学习---反向传播算法

    千次阅读 2018-12-11 16:30:15
    在介绍反向传播之前,先介绍怎么利用矩阵运算快速的计算神经网络输出。其实在上一章对这一块也提到过,不过不够详细。这里再介绍一下,帮助大家逐渐适应基于矩阵运算的表示方式。 我们先引入一个能够明确表示连接...
  • 误差反向传播算法(BP网络)

    千次阅读 2020-04-20 09:50:30
    误差反向传播网络(Error Back Propagtion,),简称为BP神经网络,是一种多层神经网络,与之相关的另一个概念是多层感知器(Multi-Layer Perceptron,MLP)。多层感知器除了输入层和输出层以外,还具有若干个隐含层...
  • 梯度反向传播(CS231n课程笔记翻译)

    千次阅读 2019-03-26 13:05:08
    CS231n课程笔记翻译:反向传播笔记 - 杜客的文章 - 知乎 译者注:本文智能单元首发,译自斯坦福CS231n课程笔记Backprop Note,课程教师Andrej Karpathy授权翻译。本篇教程由杜客翻译完成,堃堃和巩子嘉进行校对修改...
  • 反向传播算法详解

    千次阅读 2018-04-18 14:40:20
    BP算法,称“误差逆传播算法”,亦称“反向传播算法”,是迄今为止用得最多的多层神经网络学习算法。用BP算法训练的多层前馈神经网络称为“BP网络”。 算法流程 BP算法采取基于梯度下降的策略,以目标的负梯度...
  • 深度学习 --- BP算法详解(误差反向传播算法)

    万次阅读 多人点赞 2018-11-11 13:37:42
     大家看了是不是有点晕晕的呢,还是不知道到底如何反向传播的,别急,我们下面通过数学进行说明他到底是如何进行反向传播的。 我么知道误差E的来源就是实际输出和期望输出的差值即:     根据 式将误差E...
  • 你确实可以使用反向传播来训练一个优于普通反向传播的独立学习规则。 Eric Jang 认为,很多研究者之所以还没理解这个观点(即我们应该用元学习方法来模拟生物学可信的回路),是因为目前算力还不够强,无法同时训练...
  • 一步一步教你反向传播的例子

    万次阅读 多人点赞 2016-01-27 11:44:25
    背景反向传播(Backpropagation)是训练神经网络最通用的方法之一,网上有许多文章尝试解释反向传播是如何工作的,但是很少有包括真实数字的例子,这篇博文尝试通过离散的数据解释它是怎样工作的。Python实现的反向...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 20,940
精华内容 8,376
关键字:

反向传播规则