精华内容
下载资源
问答
  • 主要介绍了numpy实现神经网络反向传播算法的步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
  • 反向传播算法(Backpropagation)是目前用来训练人工神经网络(Artificial Neural Network,ANN)的最常用且最有效的算法。其主要思想是:(1)将训练集数据输入到ANN的输入层,经过隐藏层,最后达到输出层并输出...
    反向传播算法(Backpropagation)是目前用来训练人工神经网络(Artificial Neural Network,ANN)的最常用且最有效的算法。其主要思想是:
    (1)将训练集数据输入到ANN的输入层,经过隐藏层,最后达到输出层并输出结果,这是ANN的前向传播过程;
    (2)由于ANN的输出结果与实际结果有误差,则计算估计值与实际值之间的误差,并将该误差从输出层向隐藏层反向传播,直至传播到输入层;
    (3)在反向传播的过程中,根据误差调整各种参数的值;不断迭代上述过程,直至收敛。

            反向传播算法的思想比较容易理解,但具体的公式则要一步步推导,因此本文着重介绍公式的推导过程。


    1. 变量定义



            上图是一个三层人工神经网络,layer1至layer3分别是输入层、隐藏层和输出层。如图,先定义一些变量:
            表示第层的第个神经元连接到第层的第个神经元的权重;
            表示第层的第个神经元的偏置;
            表示第层的第个神经元的输入,即:
            表示第层的第个神经元的输出,即:
            其中表示激活函数。

    如果你觉得这篇文章看起来稍微还有些吃力,或者想要系统地学习人工智能,那么推荐你去看床长人工智能教程。非常棒的大神之作,教程不仅通俗易懂,而且很风趣幽默。点击这里可以查看教程。

    2. 代价函数

            代价函数被用来计算ANN输出值与实际值之间的误差。常用的代价函数是二次代价函数(Quadratic cost function):

            其中,表示输入的样本,表示实际的分类,表示预测的输出,表示神经网络的最大层数。

    3. 公式及其推导

            本节将介绍反向传播算法用到的4个公式,并进行推导。如果不想了解公式推导过程,请直接看第4节的算法步骤。
            首先,将第层第个神经元中产生的错误(即实际值与预测值之间的误差)定义为:


            本文将以一个输入样本为例进行说明,此时代价函数表示为:


    公式1(计算最后一层神经网络产生的错误):



            其中,表示Hadamard乘积,用于矩阵或向量之间点对点的乘法运算。 公式1的推导过程如下:



    公式2(由后往前,计算每一层神经网络产生的错误):



            推导过程:


    公式3(计算权重的梯度):



            推导过程:



    公式4(计算偏置的梯度):



            推导过程:



    4. 反向传播算法伪代码


    • 输入训练集

    • 对于训练集中的每个样本x,设置输入层(Input layer)对应的激活值
      • 前向传播:
    , 
      • 计算输出层产生的错误:

      • 反向传播错误:


    • 使用梯度下降(gradient descent),训练参数:

     








    展开全文
  • 快速计算梯度的魔法--反向传播算法

    千次阅读 2017-06-16 15:40:59
    前向传递节点,反向传递梯度。 我们先从计算图的底部开始向上,逐个节点计算函数值并保存下来。这个步骤,叫做前向计算(forward)。...这个步骤,叫做反向传播(backward)或者更明确一点叫做反向梯度传播。

    一、实验介绍

    1.1 实验内容

    第一次实验最后我们说了,我们已经学习了深度学习中的模型model(神经网络)、衡量模型性能的损失函数和使损失函数减小的学习算法learn(梯度下降算法),还了解了训练数据data的一些概念。但是还没有解决梯度下降算法中如何求损失函数梯度的问题。

    本次实验课,我们就来学习一个能够快速计算梯度的算法--反向传播算法(backpropogate algorithm),这个算法在神经网络中非常重要,同时这个算法也非常巧妙,非常好玩。

    我们还会在本次实验课中用代码实现反向传播算法。

    1.2 实验知识点

    • 链式法则与“计算图”的概念
    • 反向传播算法

    1.3 实验环境

    • python 2.7
    • numpy 1.12.1

    二、实验步骤

    2.1 计算梯度的数值方法

    第一次实验我留的一个课后作业里问你是否能够想出一个求解梯度的办法,其实不难想到一种简单的办法就是使用“数值法”计算梯度。
    办法很简单,就是对于损失函数中的一个初始取值为a0的参数a,先计算当前的损失函数值J0,再保持其他参数不变,而使a改变一个很小的量,比如变成a0+0.000001,再求改变之后的损失函数值J1。然后(J1-J0)/0.000001就是J对于a的偏导的近似值。我们对每一个参数采用类似的方法求偏导,最后将偏导的值组成一个向量,即为梯度向量。
    这个办法看上去很简单,但却无法应用在实际的神经网络当中。一方面的原因是,我们很难知道对参数的改变,有多小才算足够小,即我们很难保证最后求出的梯度是准确的。
    另一方面的原因是,这种方法计算量太大,现在的神经网络中经常会有上亿个参数,而这里每求一个分量的偏导都要把所有参数值代入损失函数求两次损失函数值,而且每个分量都要执行这样的计算。相当于每计算一次梯度需要2x1亿x1亿次计算,而梯度下降算法又要求我们多次(可能是上万次)计算梯度。这样巨大的计算量即使是超级计算机也很难承受(世界第一的“神威·太湖之光”超级计算机峰值性能为12.5亿亿次/秒,每秒也只能计算大概6次梯度)。

    所以,我们需要更加高效准确的算法来计算梯度,而反向传播算法正好能满足我们的需求。

    2.2 “计算图(compute graph)”与链式法则

    其实如果你已经理解了链式法则,那么可以说,你几乎已经学会反向传播算法了。让人感到很愉快对不对,好像什么都还没做,我们就已经掌握了一个名字看起来有些吓人的算法。
    为了帮助我们真正理解反向传播算法,我们先来看一下什么是“计算图”,我们以第一次实验提到的sigmoid函数为例:

    它的计算图,是这样的:

    此处输入图片的描述

    我们将sigmoid函数视为一个复合函数,并将其中的每一个子函数都视为一个节点,每个节点按照复合函数实际的运算顺序链接起来,最终得到的F其实就是sigmoid函数本身。

    根据求导法则,我们可以求得每一个节点对它直接子节点的导函数:

    此处输入图片的描述

    最重要的地方来了,再根据求导链式法则,我们现在可以轻易写出图中任意一个高层节点对其任意后代节点的导函数:只需要把连接它们的路径上的所有部分导函数都乘起来就可以了。
    比如:

    dF/dC=(dF/dE)*(dE/dC)=(-1/E^2)*1=-1/E^2
    dF/dA=(dF/dE)*(dE/dC)*(dC/dB)*(dB/dA)=(-1/E^2)*(1)*(e^B)*(-1)=e^B/E^2

    2.3 反向传播算法

    到这里反向传播算法已经呼之欲出了,对于一个具体的参数值,我们只需要把每个节点的值代入求得的导函数公式就可以求得导数(偏导数),进而得到梯度。
    这很简单,我们先从计算图的底部开始向上,逐个节点计算函数值并保存下来。这个步骤,叫做前向计算(forward)

    然后,我们从计算图的顶部开始向下,逐步计算损失函数对每个子节点的导函数,代入前向计算过程中得到的节点值,得到导数值。这个步骤,叫做反向传播(backward)或者更明确一点叫做反向梯度传播
    我们来具体实践一下,对于上图中的sigmoid函数,计算x=0时的导数:
    前向计算:

    A=0, B=0, C=1, D=1, E=2, F=-1/4

    反向传播:

    dF/dE=-1/E^2=-1/2^2=-1/4
    dF/dC=dF/dE*dE/dC=-1/4
    dF/dB=dF/dC*dC/dB=-1/4*e^B=-1/4*1=-1/4
    dF/dA=dF/dB*dB/dA=-1/4*(-1)=1/4

    以上就是反向传播算法的全部内容。对于有1亿个参数的损失函数,我们只需要2*1亿次计算就可以求出梯度。复杂度大大降低,速度将大大加快。

    2.4 将sigmoid视为一个整体

    sigmoid函数中没有参数,在实际的神经网络中,我们都是将sigmoid函数视为一个整体来对待,没必要求它的内部节点的导函数。
    sigmoid函数的导函数是什么呢?你可以自己求导试试,实际上sigmoid(x)'=sigmoid(x)*(1-sigmoid(x))

    2.5 反向传播算法--动手实现

    激动人心的时刻到了,我们终于要开始用python代码实现深度神经网络的过程,这里我们打算对第一次实验中的神经网络示例图中的“复合函数”编写反向传播算法。不过为了循序渐进,我们考虑第一层(输入层)只有两个节点,第二层只有一个节点的情况,即如下图:

    此处输入图片的描述

    注意我们将sigmoid函数图像放在了b1节点后面,代表我们这里对b1运用sigmoid函数得到了最终的输出h1。

    如果你对自己比较有信心,可以不看接下来实现的代码,自己动手试一试。

    我们可以先把图中包含的函数表达式写出来,方便我们之后写代码参考:
    b1=w11*a1+w12*a2+bias1
    h1=sigmoid(b1)
    h1=sigmoid(w11*a1+w12*a2+bias1)

    现在我们创建bp.py文件,开始编写代码。先来编写从第一层到第二层之间的代码:

    import numpy as np
    
    class FullyConnect:
        def __init__(self, l_x, l_y):  # 两个参数分别为输入层的长度和输出层的长度
            self.weights = np.random.randn(l_y, l_x)  # 使用随机数初始化参数
            self.bias = np.random.randn(1)  # 使用随机数初始化参数
    
        def forward(self, x):
            self.x = x  # 把中间结果保存下来,以备反向传播时使用
            self.y = np.dot(self.weights, x) + self.bias  # 计算w11*a1+w12*a2+bias1
            return self.y  # 将这一层计算的结果向前传递
    
        def backward(self, d):
            self.dw = d * self.x  # 根据链式法则,将反向传递回来的导数值乘以x,得到对参数的梯度
            self.db = d
            self.dx = d * self.weights
            return self.dw, self.db  # 返回求得的参数梯度,注意这里如果要继续反向传递梯度,应该返回self.dx
    

    注意在神经网络中,我们将层与层之间的每个点都有连接的层叫做全连接(fully connect)层,所以我们将这里的类命名为FullyConnect
    上面的代码非常清楚简洁,我们的全连接层完成了三个工作:

    1. 随机初始化网络参数
    2. 根据x计算这层的输出y,并前向传递给下一层
    3. 运用求导链式法则,将前面的网络层向后传递的导数值与本层的相关数值相乘,得到最后一层对本层参数的梯度。注意这里如果要继续反向传递梯度(如果后面还有别的层的话),backward()应该返回self.dx

    然后是第二层的输入到最后的输出之间的代码,也就是我们的sigmoid层:

    class Sigmoid:
        def __init__(self):  # 无参数,不需初始化
            pass
    
        def sigmoid(self, x):
            return 1 / (1 + np.exp(x))
    
        def forward(self, x):
            self.x = x
            self.y = self.sigmoid(x)
            return self.y
    
        def backward(self):  # 这里sigmoid是最后一层,所以从这里开始反向计算梯度
            sig = self.sigmoid(self.x)
            self.dx = sig * (1 - sig)
            return self.dx  # 反向传递梯度
    

    由于我们要多次使用sigmoid函数,所以我们单独的把sigmoid写成了类的一个成员函数。

    我们这里同样完成了三个工作。只不过由于Sigmoid层没有参数,所以不需要进行参数初始化。同时由于这里需要反向传播梯度,所以backward()函数必须返回self.dx

    把上面的两层拼起来,就完成了我们的总体的网络结构:

    def main():
        fc = FullyConnect(2, 1)
        sigmoid = Sigmoid()
        x = np.array([[1], [2]])
        print 'weights:', fc.weights, ' bias:', fc.bias, ' input: ', x
    
        # 执行前向计算
        y1 = fc.forward(x)
        y2 = sigmoid.forward(y1)
        print 'forward result: ', y2
    
        # 执行反向传播
        d1 = sigmoid.backward()
        dx = fc.backward(d1)
        print 'backward result: ', dx
    
    
    if __name__ == '__main__':
        main()
    

    请你自行运行上面的代码,并修改输入的x值。观察输出的中间值和最终结果,并手动验证我们计算的梯度是否正确。

    此处输入图片的描述

    如果你发现你不知道如何手动计算验证结果,那说明你还没有理解反向传播算法的原理,请回过头去再仔细看一下之前的讲解。

    这里给出完整代码的下载链接,但我还是希望你能尽量自己尝试写出代码,至少自己动手将上面的代码重新敲一遍。这样学习效果会好得多。

    完整代码文件下载:

    wget http://labfile.oss.aliyuncs.com/courses/814/bp.py
    

    2.6 层次化的网络结构

    上面的代码将每个网络层写在不同的类里,并且类里面的接口都是一致的(forward 和 backward),这样做有很多好处,一是最大程度地降低了不同模块之间的耦合程度,如果某一个层里面的代码需要修改,则只需要修改该层的代码就够了,不需要关心其他层是怎么实现的。另一方面可以完全自由地组合不同的网络层(我们最后会介绍神经网络里其他种类的网络层)。
    实际上,目前很多用于科研和工业生产的深度学习框架很多都是采用这种结构,你可以找一个深度学习框架(比如caffe)看看它的源码,你会发现里面就是这样一个个写好的网络层。

    三、实验总结

    本次实验,我们完全地掌握了梯度下降算法中的关键--反向传播算法。至此,神经网络中最基本的东西你已经全部掌握了。你现在完全可以自己尝试构建神经网络并使用反向传播算法优化网络中的参数。
    如果你把到此为止讲的东西差不多都弄懂了,那非常恭喜你,你应该为自己感到骄傲。如果你暂时还有些东西没有理解,不要气馁,回过头去仔细看看,到网上查查资料,如果实在无法理解,问问我们实验楼的助教,我相信你最终也能理解。
    本次实验,我们学习了:

    • 使用计算图理解反向传播算法
    • 层次化的神经网络结构

    四、课后作业

    1. [选做]请你自己尝试将我们上面实现的第二层网络的节点改为2个(或多个),注意这里涉及到对矩阵求导,如果你没学过相关知识可能无法下手。
    展开全文
  • 为了在保证图像质量的前提...实验结果表明,DR-BP算法相比仅适用于单站式成像的快速傅里叶变换算法,重建图像边缘干扰少,相比传统的反向传播算法,重建速度大幅提升,本文实验中获得的图像质量相同时,重建速度可提升60倍。
  • 人工神经网络是模拟生物神经系统的。神经元之间是通过轴突、树突互相连接...而反向传播(back propagation)算法就是用来调整权值的。 核心思想 训练误差逐层反向传播,每层神经元与下层神经元间权重通过误差最...

    人工神经网络是模拟生物神经系统的。神经元之间是通过轴突、树突互相连接的,神经元收到刺激时,神经脉冲在神经元之间传播,同时反复的脉冲刺激,使得神经元之间的联系加强。受此启发,人工神经网络中神经元之间的联系(权值)也是通过反复的数据信息"刺激"而得到调整的。而反向传播(back propagation)算法就是用来调整权值的。

    核心思想

    训练误差逐层反向传播,每层神经元与下层神经元间权重通过误差最速梯度下降的方法调整。

    算法简介

    人工神经网络简介

    通常人工神经网络分为输入层、隐藏层和输出层。隐藏层和输出层都有相应的激励函数(模拟神经脉冲的激励方式)。隐藏层可以为多层,但实际上不超过三层为好。如图:network
    常用的激励函数有sigmoid和linear函数。如果使用神经网络来做分类的工作,那么输出层激励函数通常采用sigmoid, 若做回归工作,就采用linear函数。输入层和输出层神经元数目由训练数据集而定,而隐藏层神经元数目的设定带有很大的经验性,对经验公式 n i n p u t + n o u t p u t + 2 \sqrt {n_{input}+n_{output}} + 2 ninput+noutput +2( n i n p u t , n o u t p u t n_{input},n_{output} ninput,noutput为输入层、输出层神经元数目)向上取整的数值可作为隐藏层神经元数目。

    人工神经网络的前向传播

    训练数据包含的信息逐层从输入层传播到输出层的方式是以感知机为基础的。即 X h i d d e n _ i n = W i n p u t _ h i d d e n X i n p u t X h i d d e n _ o u t = f h i d d e n ( X h i d d e n _ i n ) X o u t p u t _ i n = W h i d d e n _ o u t p u t X h i d d e n _ o u t X o u t p u t _ o u t = f o u t p u t ( X o u t p u t _ i n ) X_{hidden\_in} = W_{input\_hidden}X_{input}\\X_{hidden\_out}=f_{hidden}(X_{hidden\_in})\\X_{output\_in} = W_{hidden\_output}X_{hidden\_out}\\X_{output\_out=f_{output}}(X_{output\_in}) Xhidden_in=Winput_hiddenXinputXhidden_out=fhidden(Xhidden_in)Xoutput_in=Whidden_outputXhidden_outXoutput_out=foutput(Xoutput_in)

    误差反向传播

    与前向传播正好相反,训练误差都是从输出层开始反向传播到每个隐藏层。有了每一层的误差就好办了,训练的目的就是减小误差,即最小化期望风险,通常采用平方误差损失函数 E = 1 2 ( y p r e d − y t r u e ) 2 E = \frac{1}{2}(y_{pred}-y_{true})^2 E=21(ypredytrue)2,采用最速梯度下降法更新权值。
    根据链式法则计算每层权值调整梯度:
    --------------------------------------------------------------------------------------
    举例如下:
    eg
    ∂ E ∂ W i n p u t _ h i d d e n = ∂ E ∂ X o u t p u t _ o u t ∂ X o u t p u t _ o u t ∂ X o u t p u t _ i n ∂ X o u t p u t _ i n ∂ X h i d d e n _ o u t ∂ X h i d d e n _ o u t ∂ X h i d d e n _ i n ∂ X h i d d e n _ i n ∂ W i n p u t _ h i d d e n \frac{\partial E}{\partial W_{input\_hidden}} = \frac{\partial E}{\partial X_{output\_out}}\frac{\partial X_{output\_out}}{\partial X_{output\_in}}\frac{\partial X_{output\_in}}{\partial X_{hidden\_out}}\frac{\partial X_{hidden\_out}}{\partial X_{hidden\_in}}\frac{\partial X_{hidden\_in}}{\partial W_{input\_hidden}} Winput_hiddenE=Xoutput_outEXoutput_inXoutput_outXhidden_outXoutput_inXhidden_inXhidden_outWinput_hiddenXhidden_in --------------------------------------------------------------------------------------

    输出层梯度: ∂ E ∂ X o u t p u t _ o u t = G o u t = X o u t p u t _ o u t − y t r u e \frac{\partial E}{\partial X_{output\_out}}=G_{out} = X_{output\_out}-y_{true} Xoutput_outE=Gout=Xoutput_outytrue即输出层的误差。

    隐藏层到输出层权值梯度: G h i d d e n _ o u t = X h i d d e n _ o u t δ h i d d e n _ o u t p u t δ h i d d e n _ o u t p u t = − G o u t ∗ f o u t p u t ′ ( X o u t p u t _ i n ) 其 中 , ∂ X o u t p u t _ o u t ∂ X o u t p u t _ i n = f o u t p u t ′ ( X o u t p u t _ i n ) G_{hidden\_out}=X_{hidden\_out}\delta_{hidden\_output}\\ \delta_{hidden\_output} = - G_{out} *f_{output}^{'}(X_{output\_in}) \\ 其中,\frac{\partial X_{output\_out}}{\partial X_{output\_in}} = f_{output}^{'}(X_{output\_in}) Ghidden_out=Xhidden_outδhidden_outputδhidden_output=Goutfoutput(Xoutput_in)Xoutput_inXoutput_out=foutput(Xoutput_in)
    输入层到隐藏层权值梯度: G i n p u t _ h i d d e n = X i n p u t δ i n p u t _ h i d d e n δ i n p u t _ h i d d e n = δ h i d d e n _ o u t p u t W h i d d e n _ o u t p u t ∗ f h i d d e n ′ ( X h i d d e n _ i n ) 其 中 , ∂ X o u t p u t _ i n ∂ X h i d d e n _ o u t = W h i d d e n _ o u t p u t , ∂ X h i d d e n _ o u t ∂ X h i d d e n _ i n = f h i d d e n ′ ( X h i d d e n _ i n ) G_{input\_hidden}=X_{input}\delta_{input\_hidden}\\\delta_{input\_hidden} = \delta_{hidden\_output} W_{hidden\_output}*f_{hidden}^{'}(X_{hidden\_in}) \\ 其中,\frac{\partial X_{output\_in}}{\partial X_{hidden\_out}}=W_{hidden\_output},\frac{\partial X_{hidden\_out}}{\partial X_{hidden\_in}} = f_{hidden}^{'}(X_{hidden\_in}) Ginput_hidden=Xinputδinput_hiddenδinput_hidden=δhidden_outputWhidden_outputfhidden(Xhidden_in)Xhidden_outXoutput_in=Whidden_output,Xhidden_inXhidden_out=fhidden(Xhidden_in)这里, δ h i d d e n _ o u t p u t W h i d d e n _ o u t p u t \delta_{hidden\_output} W_{hidden\_output} δhidden_outputWhidden_output相当于反向传播到隐藏层的误差。

    隐藏层到输出层权值更新: Δ W h i d d e n _ o u t p u t = η G h i d d e n _ o u t + α Δ W h i d d e n _ o u t p u t p r e v i o u s \Delta W_{hidden\_output}=\eta G_{hidden\_out} + \alpha\Delta W_{hidden\_output}^{previous} ΔWhidden_output=ηGhidden_out+αΔWhidden_outputprevious
    输入层到隐藏层权值更新: Δ W i n p u t _ h i d d e n = η G i n p u t _ h i d d e n + α Δ W i n p u t _ h i d d e n p r e v i o u s \Delta W_{input\_hidden}=\eta G_{input\_hidden}+\alpha\Delta W_{input\_hidden}^{previous} ΔWinput_hidden=ηGinput_hidden+αΔWinput_hiddenprevious
    注:*表示对应元素相称,其他为矩阵乘法, f f f为激励函数, α \alpha α为动量项前系数。 η \eta η为学习率

    算法流程

    • Input: 训练数据集X_data和y_data, 神经网络必要参数,阈值epsilon,最大迭代次数maxstep
    • Output: 神经网络权值W
    • Step1: 初始化权值矩阵W,阈值b
    • Step2: 迭代训练直到误差小于阈值epsilon或达到最大迭代次数maxstep。训练步骤包括前向传播和误差反向传播。

    代码

    """
    BP神经网络
    """
    import numpy as np
    import math
    
    
    # 激励函数及相应导数,后续可添加
    def sigmoid(x):
        return 1.0 / (1 + np.exp(-x))
    
    
    def diff_sigmoid(x):
        fval = sigmoid(x)
        return fval * (1 - fval)
    
    
    def linear(x):
        return x
    
    
    def diff_linear(x):
        return np.ones_like(x)
    
    
    class BP:
        def __init__(self, n_hidden=None, f_hidden='sigmoid', f_output='sigmoid',
                     epsilon=1e-3, maxstep=1000, eta=0.1, alpha=0.0):
            self.n_input = None  # 输入层神经元数目
            self.n_hidden = n_hidden  # 隐藏层神经元数目
            self.n_output = None
            self.f_hidden = f_hidden
            self.f_output = f_output
            self.epsilon = epsilon
            self.maxstep = maxstep
            self.eta = eta  # 学习率
            self.alpha = alpha  # 动量因子
    
            self.wih = None  # 输入层到隐藏层权值矩阵
            self.who = None  # 隐藏层到输出层权值矩阵
            self.bih = None  # 输入层到隐藏层阈值
            self.bho = None  # 隐藏层到输出层阈值
            self.N = None
    
        def init_param(self, X_data, y_data):
            # 初始化
            if len(X_data.shape) == 1:  # 若输入数据为一维数组,则进行转置为n维数组
                X_data = np.transpose([X_data])
            self.N = X_data.shape[0]
            # normalizer = np.linalg.norm(X_data, axis=0)
            # X_data = X_data / normalizer
            if len(y_data.shape) == 1:
                y_data = np.transpose([y_data])
            self.n_input = X_data.shape[1]
            self.n_output = y_data.shape[1]
            if self.n_hidden is None:
                self.n_hidden = int(math.ceil(math.sqrt(self.n_input + self.n_output)) + 2)
            self.wih = np.random.rand(self.n_input, self.n_hidden)  # i*h
            self.who = np.random.rand(self.n_hidden, self.n_output)  # h*o
            self.bih = np.random.rand(self.n_hidden)  # h
            self.bho = np.random.rand(self.n_output)  # o
            return X_data, y_data
    
        def inspirit(self, name):
            # 获取相应的激励函数
            if name == 'sigmoid':
                return sigmoid
            elif name == 'linear':
                return linear
            else:
                raise ValueError('the function is not supported now')
    
        def diff_inspirit(self, name):
            # 获取相应的激励函数的导数
            if name == 'sigmoid':
                return diff_sigmoid
            elif name == 'linear':
                return diff_linear
            else:
                raise ValueError('the function is not supported now')
    
        def forward(self, X_data):
            # 前向传播
            x_hidden_in = X_data @ self.wih + self.bih  # n*h
            x_hidden_out = self.inspirit(self.f_hidden)(x_hidden_in)  # n*h
            x_output_in = x_hidden_out @ self.who + self.bho  # n*o
            x_output_out = self.inspirit(self.f_output)(x_output_in)  # n*o
            return x_output_out, x_output_in, x_hidden_out, x_hidden_in
    
        def fit(self, X_data, y_data):
            # 训练主函数
            X_data, y_data = self.init_param(X_data, y_data)
            step = 0
            # 初始化动量项
            delta_wih = np.zeros_like(self.wih)
            delta_who = np.zeros_like(self.who)
            delta_bih = np.zeros_like(self.bih)
            delta_bho = np.zeros_like(self.bho)
            while step < self.maxstep:
                step += 1
                # 向前传播
                x_output_out, x_output_in, x_hidden_out, x_hidden_in = self.forward(X_data)
                if np.sum(abs(x_output_out - y_data)) < self.epsilon:
                    break
                # 误差反向传播,依据权值逐层计算当层误差
                err_output = y_data - x_output_out  # n*o, 输出层上,每个神经元上的误差
                delta_ho = -err_output * self.diff_inspirit(self.f_output)(x_output_in)  # n*o
                err_hidden = delta_ho @ self.who.T  # n*h, 隐藏层(相当于输入层的输出),每个神经元上的误差
                # 隐藏层到输出层权值及阈值更新
                delta_bho = np.sum(self.eta * delta_ho + self.alpha * delta_bho, axis=0) / self.N
                self.bho -= delta_bho
                delta_who = self.eta * x_hidden_out.T @ delta_ho + self.alpha * delta_who
                self.who -= delta_who
                # 输入层到隐藏层权值及阈值的更新
                delta_ih = err_hidden * self.diff_inspirit(self.f_hidden)(x_hidden_in)  # n*h
                delta_bih = np.sum(self.eta * delta_ih + self.alpha * delta_bih, axis=0) / self.N
                self.bih -= delta_bih
                delta_wih = self.eta * X_data.T @ delta_ih + self.alpha * delta_wih
                self.wih -= delta_wih
            return
    
        def predict(self, X):
            # 预测
            res = self.forward(X)
            return res[0]
    
    
    if __name__ == '__main__':
        import matplotlib.pyplot as plt
    
        N = 100
        X_data = np.linspace(-1, 1, N)
        X_data = np.transpose([X_data])
        y_data = np.exp(-X_data) * np.sin(2 * X_data)
        bp = BP(f_output='linear', maxstep=2000, eta=0.01, alpha=0.1)  # 注意学习率若过大,将导致不能收敛
        bp.fit(X_data, y_data)
        plt.plot(X_data, y_data)
        pred = bp.predict(X_data)
        plt.scatter(X_data, pred, color='r')
        plt.show()
    

    我的GitHub
    注:如有不当之处,请指正。

    展开全文
  • 定义 首先来一个反向传播算法的定义(转自维基百科):反向传播(英语:Backpropagation,缩写为BP)是“误差反向传播”的简称,是一种与最优化方法(如梯度下降法)结合使用的,用来训练人工神经网络的常见方法。...

    前言(扯犊子)

    自己学习机器学习,深度学习也有好长一段时间了,一直以来都想写点有价值的技术博客,以达到技术分享及记录自己成长的目的,奈何之前一直拖着,近来算是醒悟,打算以后不定时写一写博客,也算是作为自己不断学习,不断进步的记录。既然是写博客,希望自己的博客以后要做到“准确、生动、简洁、易懂”的水平,做到对自己、对读者负责,希望大家多交流,共同进步!

    言归正传,想起当时自己刚入门深度学习的时候,当时对神经网络的“反向传播”机制不是很理解(这对理解以后的很多概念来说,很重要!!一定要搞懂!!),当时查了很多资料,花费了很多时间,感谢当时所查阅的很多资料的作者,本篇博客就网络上很多优秀的资料和我个人的理解,争取生动、简单地讲解一下BP算法,希望能够帮助到大家。

    定义

    首先来一个反向传播算法的定义(转自维基百科):反向传播(英语:Backpropagation,缩写为BP)是“误差反向传播”的简称,是一种与最优化方法(如梯度下降法)结合使用的,用来训练人工神经网络的常见方法。 该方法对网络中所有权重计算损失函数的梯度。 这个梯度会反馈给最优化方法,用来更新权值以最小化损失函数。(误差的反向传播)

    算法讲解(耐心看)

    如果去问一下了解BP算法的人“BP算法怎推导?”,大概率得到的回答是“不就是链式求导法则嘛”,我觉得这种答案对于提问题的人来说没有任何帮助。BP的推导需要链式求导不错,但提问者往往想得到的是直观的回答,毕竟理解才是王道。直观的答案,非图解莫属了。
    注:下图的确是反向传播算法,但不是深度学习中的backprop,不过backward的大体思想是一样的,毕竟误差没法从前往后计算啊。(在深度学习中操作的是计算图—Computational graph),如果暂时不理解上面那句话,你可以当我没说过,不要紧~(手动?)

    下面通过两组图来进行神经网络前向传播反向传播算法的讲解,第一组图来自国外某网站,配图生动形象。如果对你来说,单纯的讲解理解起来比较费劲,那么可以参考第二组图——一个具体的前向传播和反向传播算法的例子。通过本篇博客,相信就算是刚刚入门的小白(只要有一点点高等数学基础知识),也一定可以理解反向传播算法!

    CASE 1(图示讲解,看不太懂没关系,看第二组图)

    首先拿一个简单的三层神经网络来举例,如下:
    在这里插入图片描述

    每个神经元由两部分组成,第一部分(e)是输入值权重系数乘积的,第二部分(f(e))是一个激活函数(非线性函数)的输出, y=f(e)即为某个神经元的输出,如下:
    在这里插入图片描述

    下面是前向传播过程:
    在这里插入图片描述
    -----------手动分割-----------
    在这里插入图片描述
    -----------手动分割-----------
    在这里插入图片描述

    到这里为止,神经网络的前向传播已经完成,最后输出的y就是本次前向传播神经网络计算出来的结果(预测结果),但这个预测结果不一定是正确的,要和真实的标签(z)相比较,计算预测结果和真实标签的误差( δ \delta δ),如下:
    在这里插入图片描述

    下面开始计算每个神经元的误差( δ \delta δ):
    在这里插入图片描述
    (If propagated errors came from few neurons they are added. The illustration is below: )

    在这里插入图片描述

    下面开始利用反向传播的误差,计算各个神经元(权重)的导数,开始反向传播修改权重(When the error signal for each neuron is computed, the weights coefficients of each neuron input node may be modified. In formulas below d f ( e ) d e \dfrac {df\left( e\right) }{de} dedf(e) represents derivative of neuron activation function (which weights are modified). ):
    在这里插入图片描述
    在这里插入图片描述
    -----------手动分割-----------
    在这里插入图片描述
    -----------手动分割-----------
    在这里插入图片描述

    Coefficient η \eta η affects network teaching speed.
    到此为止,整个网络的前向,反向传播和权重更新已经完成,推荐参考上面给出的本教程的链接,如果对纯理论讲解较难接受,没关系,强烈推荐第二组图的例子!!!

    CASE 2(具体计算举例,嫌麻烦的可直接看这个,强烈推荐!!!!!)

    首先明确,“正向传播”求损失,“反向传播”回传误差。同时,神经网络每层的每个神经元都可以根据误差信号修正每层的权重,只要能明确上面两点,那么下面的例子,只要会一点链式求导规则,就一定能看懂!

    BP算法,也叫 δ \delta δ算法,下面以3层的感知机为例进行举例讲解。
    在这里插入图片描述

    上图的前向传播(网络输出计算)过程如下:(此处为网络的整个误差的计算,误差E计算方法为mse)

    在这里插入图片描述

    上面的计算过程并不难,只要耐心一步步的拆开式子,逐渐分解即可。现在还有两个问题需要解决:

    1. 误差E有了,怎么调整权重让误差不断减小?
    2. E是权重w的函数,何如找到使得函数值最小的w。

    解决上面问题的方法是梯度下降算法(简单图示如下),大家如有不太懂的可先行查阅别的资料,只要能达到理解线性回归梯度下降算法的水平即可,这里不再赘述。
    在这里插入图片描述

    划重点,划重点,划重点!!!
    BP算法的具体例子来喽!!

    就算上面的所有东西你都看的迷迷糊糊,通过下面的例子,相信绝大多数人也能很轻松的理解BP算法。如图是一个简单的神经网络用来举例:
    在这里插入图片描述

    下面是前向(前馈)运算(激活函数为sigmoid):
    在这里插入图片描述

    下面是反向传播(求网络误差对各个权重参数的梯度):

    我们先来求最简单的,求误差E对w5的导数。首先明确这是一个“链式求导”过程,要求误差E对w5的导数,需要先求误差E对out o1的导数,再求out o1对net o1的导数,最后再求net o1对w5的导数,经过这个链式法则,我们就可以求出误差E对w5的导数(偏导),如下图所示:
    在这里插入图片描述

    导数(梯度)已经计算出来了,下面就是反向传播与参数更新过程
    在这里插入图片描述

    上面的图已经很显然了,如果还看不懂真的得去闭门思过了(开玩笑~),耐心看一下上面的几张图,一定能看懂的。

    如果要想求误差E对w1的导数,误差E对w1的求导路径不止一条,这会稍微复杂一点,但换汤不换药,计算过程如下所示:
    在这里插入图片描述

    至此,“反向传播算法”及公式推导的过程总算是讲完了啦!个人感觉,尤其是第二组图,还算是蛮通俗易懂的,希望能帮助到大家,共同进步!

    感觉本篇讲的有点啰嗦了,直接放第二组图可能会更简洁,以后争取改进。

    以上(麻烦大家 点赞 + 关注 一波啊)

    References

    http://galaxy.agh.edu.pl/~vlsi/AI/backp_t_en/backprop.html
    https://www.cnblogs.com/charlotte77/p/5629865.html
    https://blog.csdn.net/han_xiaoyang

    展开全文
  • 反向传播算法(BP算法)学习总结 1、简介   BP算法是由学习过程由信号的正向传播与误差的反向传播两个过程组成。由于多层前馈网络的训练经常采用误差反向传播算法,人们也常把将多层前馈网络直接称为BP网络。 正向...
  • 深度学习(一):DNN前向传播算法和反向传播算法

    万次阅读 多人点赞 2018-11-29 17:32:13
    文章目录一、深度神经网络(DNN)模型1.1 从感知机到神经网络1.2 DNN的基本结构二、DNN前向传播算法2.1 DNN前向传播算法数学原理2.2 DNN前向传播算法2.3 DNN前向传播算法小结三、DNN反向传播算法3.1 DNN反向传播算法...
  • 吴恩达机器学习 - 神经网络的反向传播算法

    千次阅读 多人点赞 2018-06-21 20:59:35
    反向传播(填充在nnCostFunction.m中,代价函数计算代码之下, 注意这里没有正则化 ): 公式和图示: %开始反向传播,分5部计算梯度 %1.对于输入层,计算每个样本的激活值(上面已经实现) %2.计算...
  • 一、反向传播算法 定义:反向传播(Backpropagation,缩写为BP)是“误差反向传播”的简称,其与最优化方法(如梯度下降法)的结合使用 是 用来训练人工神经网络的常用方法。 (该部分的讲解主要参考aift博主的原创文章...
  • 反向传播算法 这个网络只有3层,分别是蓝色的输入层、绿色的隐藏层和红色的输出层。 假设给了m个训练样本,第i个输入输出对表示为: 其中,x和y是3维向量。对于输入x,我们把g称作神经网络的预测(输出)值。 ...
  • 反向传播算法推导-全连接神经网络

    千次阅读 2018-07-07 10:33:51
    反向传播算法是人工神经网络训练时采用的一种通用方法,在现代深度学习中得到了大规模的应用。全连接神经网络(多层感知器模型,MLP),卷积神经网络(CNN),循环神经网络(RNN)中都有它的实现版本。算法从多元...
  • 反向传播算法推导-卷积神经网络

    千次阅读 2018-08-08 11:57:32
    在SIGAI之前的公众号文章“反向传播算法推导-全连接神经网络”中,我们推导了全连接神经网络的反向传播算法。其核心是定义误差项,以及确定误差项的递推公式,再根据误差项得到对权重矩阵、偏置向量的...
  • BP神经网络:误差反向传播算法公式推导 开端: BP算法提出 1. BP神经网络参数符号及激活函数说明 2. 网络输出误差(损失函数)定义 3. 隐藏层与输出层间的权重更新公式推导 4. 输入层与隐藏层间的权重更新...
  • 三组模拟实验的经验和t检验结果,包括ORL人脸图像数据库上的人脸识别任务以及从机器学习数据库的UCI存储库中抽取的数据集上的四个基准分类任务,表明TP-ES-BP算法取得了显著成效与SBP和最新的情绪反向传播(EmBP)...
  • 学习速率选取原则:在调整学习速率时,既需要使其足够小,保证不至于发生超调,也要保证它足够大,以使损失函数能够尽快下降,从而可通过较少次数的迭代更快地完成学习 3、多层网络求解梯度——反向传播算法 反向...
  • 大会也邀请到了人工智能各领域多位世界级的专家,包括英国两院院士、英国曼彻斯特大学教授、智源学术顾问委员会委员Steve Furber,瑞士AI实验室教授、LSTM之父Jürgen Schmidhuber,美国工程院院士、数值优化权威...
  • 在讲解误差反向传播算法之前,我们来回顾一下信号在神经网络中的流动过程。请细细体会,当输入向量\(X\)输入感知器时,第一次初始化权重向量\(W\)是随机组成的,也可以理解成我们任意设置了初始值,并和输入做点积...
  • 关于利用反向传播算法计算梯度,可以重点参考: Backpropagation Algorithm 备注, 也许有人会有疑问,反向传播到底是用来计算梯度的?还是仅仅用来逐层计算误差的??,为何这里所写的反向传播只计算了误差,而...
  • 下面将以目前流行的计算图的方式,展示一个神经网络的计算,是如何按照前向或反向传播过程组织起来的。 1、计算图(Computation Graph)的计算 尝试计算函数J,J是由三个变量a,b,c组成的函数,这个函数是3(a+bc)...
  • Iris数据集(https://en.wikipedia.org/wiki/Iris_flower_data_set)是常用的分类实验数据集,由Fisher,1936收集整理。Iris也称鸢尾花卉数据集,是一类多重变量分析的数据集。数据集包含150个数据集,分为3类,每类...
  • 前言本文基于反向传播算法的原理,实现了一个基于numpy和python的三层全连接神经网络,用于分类任务。其中在实现过程中,将会用代码的形式呈现梯度消失的现象,本文中的符号请参考我的前文《反向传播算法的公式推导...
  • 在本练习中,您将实现神经网络的反向传播算法,并将其应用于手写数字识别任务。在之前的练习中,已经实现了神经网络的前馈传播,并使用Andrew Ng他们提供的权值来预测手写数字。在本练习中,将自己实现反向传播算法...
  • BP神经网络算法即误差逆传播算法(error Back Propagation),先将输入层输入的数据提供给输入层神经元,然后逐层将信号前传,直到产生输出层的结构;然后计算输出层的误差,再将误差逆向传播至隐层神经元,最后根据...
  • 上期的文章写的比较晦涩难懂,也留下了一个问题,就是反向传播算法(backpropagation algorithm)。写的这么晦涩一来是因为我确实看的比较艰难,从看书,到敲代码、调试运行代码,用了太长时间,要保证定期发送,写...
  • 误差反向传播学习算法 实现Iris数据分类 Denverg Secret Number 29,April 2018 实验目的 用C++实现BP神经网络 实验原理 人工神经网络模型 人们从40年代开始研究人脑神经元功能。1943年心理学家...
  • 零基础入门深度学习(3) - 神经网络和反向传播算法

    万次阅读 多人点赞 2018-01-09 09:45:30
    在上一篇文章中,我们已经掌握了机器学习的基本套路,对模型、目标函数、优化算法这些概念有了一定程度的理解,而且已经会训练单个的感知器或者线性单元了。在这篇文章中,我们将把这些单独的单元按照一定的规则相互...
  • 针对LED光谱数学模型非线性的特点,提出利用一种经改进遗传算法(GA)优化的反向传播(BP)神经网络对LED光谱模型进行辨识。通过改进GA的算子,提高算法收敛效果和辨识精度,利用改进GA对BP神经网络初始和权值阈值进行...
  • 为了提高识别矿山水害水源(即,判定水的类型)的正确率,利用免疫算法设计并优化了反向传播神经元网络(BPNN)的结构并求得BPNN的各层权系数和阈值的初值,用该初值训练BPNN,获得最佳的BPNN各层的权系数(权重)和阈值,使其...
  • 提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 神经网络小白初探——感知学习和反向传播算法 Perceptron Learning and Backpropagation 前言 关于感知机和反向传播几个小问题 提示:以下是本篇...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 17,919
精华内容 7,167
关键字:

反向传播算法实验