求助,应用BP神经网络逼近非线性函数

求助,应用BP神经网络逼近非线性函数,第1张

该作业要求不可使用Matlab自带的神经网络函数,这是因为如果允许使用,则三个函数:newff函数建立网络、train函数训练、sim函数就直接完成作业了。

下面这个附件的第二个案例,就是自己编程,使用BP算法逼近非线性函数y=x1^2+x2^2该函数为双自变量的非线性函数,完全符合你的作业的要求,可以说你可以直接不用修改,提交该代码作为你的作业。但建议你还是改一下,例如将函数换成其他非线性函数如三角函数等。也可使用改进的如加动量项、自适应学习率、引入陡度因子等方法。

BP(Back Propagation)神经网络是1986年由Rumelhart和McCelland为首的科学家小组提出,是一种按误差逆传播算法训练的多层前馈网络,是目前应用最广泛的神经网络模型之一。BP网络能学习和存贮大量的输入-输出模式映射关系,而无需事前揭示描述这种映射关系的数学方程。它的学习规则是使用最速下降法,通过反向传播来不断调整网络的权值和阈值,使网络的误差平方和最小。BP神经网络模型拓扑结构包括输入层(input)、隐层(hidden layer)和输出层(output layer)。

学习神经网络这段时间,有一个疑问,BP神经网络中训练的次数指的网络的迭代次数,如果有a个样本,每个样本训练次数n,则网络一共迭代an次,在n>>a 情况下 , 网络在不停的调整权值,减小误差,跟样本数似乎关系不大。而且,a大了的话训练时间必然会变长。 

换一种说法,将你的数据集看成一个固定值, 那么样本集与测试集 也可以按照某种规格确定下来如7:3 所以如何看待 样本集的多少与训练结果呢? 或者说怎么使你的网络更加稳定,更加符合你的所需 。

我尝试从之前的一个例子中看下区别

如何用70行Java代码实现深度神经网络算法

作者其实是实现了一个BP神经网络 ,不多说,看最后的例子

一个运用神经网络的例子 

最后我们找个简单例子来看看神经网络神奇的效果。为了方便观察数据分布,我们选用一个二维坐标的数据,下面共有4个数据,方块代表数据的类型为1,三角代表数据的类型为0,可以看到属于方块类型的数据有(1,2)和(2,1),属于三角类型的数据有(1,1),(2,2),现在问题是需要在平面上将4个数据分成1和0两类,并以此来预测新的数据的类型。

描述

我们可以运用逻辑回归算法来解决上面的分类问题,但是逻辑回归得到一个线性的直线做为分界线,可以看到上面的红线无论怎么摆放,总是有一个样本被错误地划分到不同类型中,所以对于上面的数据,仅仅一条直线不能很正确地划分他们的分类,如果我们运用神经网络算法,可以得到下图的分类效果,相当于多条直线求并集来划分空间,这样准确性更高。 

描述

简单粗暴,用作者的代码运行后 训练5000次 。根据训练结果来预测一条新数据的分类(3,1)

预测值 (3,1)的结果跟(1,2)(2,1)属于一类 属于正方形

这时如果我们去掉 2个样本,则样本输入变成如下

//设置样本数据,对应上面的4个二维坐标数据 double[][] data = new double[][]{{1,2},{2,2}}; //设置目标数据,对应4个坐标数据的分类 double[][] target = new double[][]{{1,0},{0,1}};

1

2

3

copy来的:

lc;

P=[110 0807 240 02 15 1 18 2 15;

110 2865 240 01 15 2 12 1 2;

110 259 240 01 12 4 24 1 15;

220 06 240 03 12 3 18 2 1;

220 3 240 03 25 3 21 1 15;

110 1562 240 03 15 3 18 1 15;

110 0547 240 03 15 1 9 2 15];

%110 1318 300 01 15 2 18 1 2];

T=[54248 162787 168380 314797;

28614 63958 69637 82898;

86002 402710 644415 328084;

230802 445102 362823 335913;

60257 127892 76753 73541;

34615 93532 80762 110049;

56783 172907 164548 144040];

%40907 117437 120368 130179];

m=max(max(P));

n=max(max(T));

P=P'/m;

T=T'/n;

%-------------------------------------------------------------------------%

pr(1:9,1)=0; %输入矢量的取值范围矩阵

pr(1:9,2)=1;

bpnet=newff(pr,[12 4],, 'traingdx', 'learngdm');

%建立BP神经网络, 12个隐层神经元,4个输出神经元

%tranferFcn属性 'logsig' 隐层采用Sigmoid传输函数

%tranferFcn属性 'logsig' 输出层采用Sigmoid传输函数

%trainFcn属性 'traingdx' 自适应调整学习速率附加动量因子梯度下降反向传播算法训练函数

%learn属性 'learngdm' 附加动量因子的梯度下降学习函数

nettrainParamepochs=1000;%允许最大训练步数2000步

nettrainParamgoal=0001; %训练目标最小误差0001

nettrainParamshow=10; %每间隔100步显示一次训练结果

nettrainParamlr=005; %学习速率005

bpnet=train(bpnet,P,T);

%-------------------------------------------------------------------------

p=[110 1318 300 01 15 2 18 1 2];

p=p'/m;

r=sim(bpnet,p);

R=r'n;

display(R);

反向传播算法可以说是神经网络最基础也是最重要的知识点。基本上所以的优化算法都是在反向传播算出梯度之后进行改进的。同时,也因为反向传播算法是一个递归的形式,一层一层的向后传播误差即可,很容易实现(这部分听不懂没关系,下面介绍)。不要被反向传播吓到,掌握其核心思想就很容易自己手推出来。

我们知道神经网络都是有一个loss函数的。这个函数根据不同的任务有不同的定义方式,但是这个loss函数的目的就是计算出当前神经网络建模出来输出的数据和理想数据之间的距离。计算出loss之后,根据反向传播算法就可以更新网络中的各种参数以此使loss不断下降,即可使输出的数据更加理想。

所以,现在的任务是,已知一个网络的loss之后,如何根据loss来更新参数呢?具体点即如何更新网络节点中的权重w和偏差b的值呢?

这里我们采用的是全连接神经网络进行说明。

要想把这个过程说清楚,首先需要将神经网络中各个参数用文字表达清楚。定义的就是w和b在网络中的准确位置。

对于 表示的是神经网络中第 层第k个节点到神经网络中第 层第j个节点之间的权重。注意w的下标是首位表示的是节点后层节点的位置,末尾表示是前层节点的位置。理解这样的表达方式在后面的计算中会很好理解。

同理,对于b的表示:

b的表示相比于w要简单一些,符号 表示第l层网络在第j个节点的偏置。无论w还是b的表示,上标都是表示层数。并且 和 表示都是第l层网络第j个节点的参数。所以该节点的输出可以表示为:

神经网络输出之后会经过一个激活函数,这用激活函数用 表示,则经过激活函数输出为:

至此,根据上面符号 、 、 、 。我们可以对于神经网络里面每一个数据准确的表示了。

给定一个损失函数之后,用 表示,说白了反向传播就是求∂C/∂w和∂C/∂b,然后将这个值乘以和对应的w,b进行相减就可以实现一次的参数更新了。为什么这样的 *** 作就可以优化网络,减小loss值呢?

来源于导数的概念和速度相关。∂C/∂w和∂C/∂b相当于loss值C相对于w和v变化的速度。如果∂C/∂w是正的,则增大w,C也会增大,如果希望C减小的话,应该减小w;并且∂C/∂w的绝对值越大,表示w对C的值影响越大,w稍微有一点变化,C就会有大幅变化。如果要优化C变小,w应该对应的减少多少呢?也没有一个确定的答案。这里通过变化的速度和学习率相乘作为一个减小的值。通过多轮迭代。最终是希望c达到最小点。而当函数落入最小值的时候,无论是局部最小还是全局最小,其周围一定是平滑的。所以此时∂C/∂w和∂C/∂b将会变得很小甚至为0,即参数不在更新了。当函数在局部最小点处参数不在更新出现梯度消失的问题时,目前也有各种trick进行解决。不是这里的重点。

为了好说明,这里定义一个很简单的损失函数C:

接下来就是有意思的阶段了。这里还是利用上一节中∂C/∂w和∂C/∂b的解释。如果我们想要求出∂C/∂w和∂C/∂b的值,即具体的 、 对C影响速率的值,我们找一个中间变量∂C/∂ 。因为我们知道:

我们定义:

当我们知道了 值之后,我们根据 式子可以很容易求出 。

利用导数的链式法则:

很容易推出来不是?同理可以求出:

可以看出通过媒介 很容易求出∂C/∂w和∂C/∂b。那么我们现在来理解一下 到底是什么意思,以及如何求出来每一个l层j节点的 值。

根据定义:

可以看出来 就是 对于C的影响大小(联系之前说的导数和速率的关系)。而 是第 层第 个神经元未进过激活函数之前的输出。所以我们可以理解 为网络中第 层第 个神经元对loss的影响。所以很直观的看法就是我们先求出单个神经元对loss值得影响,然后再计算该神经元内部参数对于loss的影响。

ok,如果我们已经理解了为什么要引入 变量以及如何利用该变量计算具体参数的梯度后,接下来我们就可以看看如何获得 值。反向传播的名字我想也就是通过计算 的方式而来的。是一层一层递归而来的。

既然说是递归的方式,我们来思考一下 和 之间有什么关系,如果找到这个关系之后,我们就可以默认我们如果知道最后一层网络节点的 值,我们就可以获得倒数第二层网络节点的 值,倒数第三层,倒数第四层,……以此推类即可获得整个网络的每个节点的 值。至此我们的反向传播也基本完成了。

所以最重要的有两点:

先看问题1,直接根据求导的链式法则就可以找出两个的关系,具体公式如下,可以多看看手写一下,思路上也很简单。

觉得这样的链式公式还是很直观的,如果不好理解,可以自己画一个神经网络图,连上节点与节点之间的线,标上参数,然后推一下应该就能理解了。

这里的 都表示的未经过激活函数的神经元的输出。 表示激活函数。因为:

所以:

带入上式就可以得出:

至此就找出了 和 之间的关系了。

(还能简化,根据最开始我们定义的 )。

理解起来就是网络中前面一层某一个神经元对于loss的影响与该层的后一层所有的神经元对loss的影响、该神经元的输出大小、该神经元与后一层神经元连接的权重有关系的,并且是一个累加的效应。这样的理解也是非常直观合乎常理的。

现在万事具备,只差问题2了。即假设最后一层网络是L,最后一层 如何计算得出。最后一层的 值就像一个导火索,一旦有了开始,就可以利用我们之前推出来的: 公式进行反向传播了(反向传播还是很形象的不是?)。现在解决这个问题。这个问题就是和损失函数具体怎么定义有关系了。不过我们先不考虑C的具体形式,根据通用的链式法则我们可以得到:

这里需要注意的是最后一层激活函数使用的是哪种。最后一层激活函数在计算某一个神经元的输出时可能会结合其他节点的输出来计算。比如softmax激活函数,其输出的是一个概率值0,1。输出大小就是结合输出所有的值。

现在我们来考虑两个具体的损失函数,并且采用之前定义的均方误差损失函数 :

求导为:

因为sigmoid输出的值仅仅和输入的x值有关 。所以 当 时值为0所以:

根据上面,BP推导有三部曲,先求出 ,再根据 分别求出 、 。总结公式如下:

启动上面反传的导火索是最后一层的 值,计算公式为:

根据最后一层不同类型的激活函数不同对待。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/12178433.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-21
下一篇 2023-05-21

发表评论

登录后才能评论

评论列表(0条)

保存