BP神经网络的matlab实现

1 BP算法原理

BP算法是利用输出层的误差来估计输出层的直接前导层的误差,再用这个误差估计更前一层的误差。如此下去,就获得了所有其他各层的误差估计。这样就形成了将输出端表现出的误差沿着与输入信号传送相反的方向逐级向网络的输入端传递的过程。因此,人们就又将此算法称为向后传播算法,简称BP算法。

2 BPNN的学习过程

–输入样本---输入层---各隐层---输出层

判断是否转入反向传播阶段:

–若输出层的实际输出与期望的输出不符

误差反传

–误差以某种形式在各层表示----修正各层单元的权值

最终达到:

网络输出的误差减少到可接受的程度

进行到预先设定的学习次数为止

3 BPNN的标准学习算法

输入层与中间层的连接权值:$w_{ih}$

隐含层与输出层的连接权值:$w_{ho}$

隐含层各神经元的阈值:$b_h$

输出层各神经元的阈值:$b_o$

样本数据个数:$k=1,2,\cdots,m$

激活函数: $f(\cdot)$

误差函数:$e=\frac{1}{2}\sum^q_{o=1}(d_o(k)-yo_o(k))^2$

第一步,网络初始化

–给各连接权值分别赋一个区间(-1,1)内的随机数,设定误差函数$e$,给定计算精度值$\varepsilon$和最大学习次$M$。

第二步,随机选取第$k$个输入样本及对应期望输出

$$ x(k)=(x_1(k),x_2(k),\cdots,x_n(k))\\ d_o(k)=(d_1(k),d_2(k),\cdots,d_q(k))\\ $$

第三步,计算隐含层各神经元的输入和输出:

$$ hi_h(k)=\sum^n_{i=1}w_{ih}x_i(k)-b_h \quad h=1,2,\cdots,p\\ ho_h(k)=f(hi_h(k)) \quad h=1,2,\cdots,p\\ yi_o(k)=\sum^p_{h=1}w_{ho}ho_h(k)-b_o \quad o=1,2,\cdots,q\\ yo_o(k)=f(yi_o(k)) \quad o=1,2,\cdots,q\\ $$

第四步,利用网络期望输出和实际输出,计算误差函数对输出层的各神经元的偏导数$\delta_o(k)$。

$$ \frac{\partial e}{\partial w_{ho}}=\frac{\partial e}{\partial yi_o}\frac{\partial yi_o}{\partial w_{ho}}\\ \frac{\partial yi_o(k)}{\partial w_{ho}}=\frac{\partial(\sum^p_hw_{ho}ho_h(k)-b_o)}{\partial w_{ho}}=ho_h(k)\\ \frac{\partial e}{\partial yi_o}=\frac{\partial\frac{1}{2}\sum^q_{o=1}(d_o(k)-yo_o(k))^2}{\partial yi_o}=-(d_o(k)-yo_o(k))yo'_o(k)\\ =-(d_o(k)-yo_o(k))f'(yi_o(k)) \dot=-\delta_o(k) $$

第五步,利用隐含层到输出层的连接权值、输出层的 $\delta_o(k)$和隐含层的输出计算误差函数对隐含层各神经元的偏导数$\delta_h(k)$

$$ \frac{\partial e}{\partial w_{ho}}=\frac{\partial e}{\partial yi_o}\frac{\partial yi_o}{\partial w_{ho}}=-\delta_o(k)ho_h(k)\\ \frac{\partial e}{\partial w_{ih}}=\frac{\partial e}{\partial hi_h(k)}\frac{\partial hi_h(k)}{\partial w_{ih}}\\ \frac{\partial hi_h(k)}{\partial w_{ih}}=\frac{\partial(\sum^n_{i=1}w_{ih}x_i(k)-b_h)}{\partial w_{ih}}=x_i(k) $$

第六步,利用输出层各神经元的$ \delta_o(k)$和隐含层各神经元的输出来修正连接权值$w_{ho}(k)$

$$ \Delta w_{ho}(k)=-\mu\frac{\partial e}{\partial w_{ho}}=\mu\delta_o(k)ho_h(k)\\ w_{ho}^{N+1}=w_{ho}^N+\eta\delta_o(k)ho_h(k)\\ $$

第七步,利用隐含层各神经元的$ \delta_h(k)$和输入层各神经元的输入修正连接权。

$$ \Delta w_{ih}(k)=-\mu\frac{\partial e}{\partial w_{ih}}=-\mu\frac{\partial e}{\partial hi_h(k)}\frac{\partial hi_h(k)}{\partial w_{ih}}=\delta_h(k)x_i(k)\\ w_{ih}^{N+1}=w_{ih}^N+\eta\delta_h(k)x_i(k)\\ $$

第八步,计算全局误差

$$ E=\frac{1}{2m}\sum^m_{k=1}\sum^q_{o=1}(d_o(k)-y_o(k))^2\\ $$

第九步,判断网络误差是否满足要求。当误差达到预设精度或学习次数大于设定的最大次数,则结束算法。否则,选取下一个学习样本及对应的期望输出,返回到第三步,进入下一轮学习。

4 BPNN的matlab实现

函数newff之前讲过了:

net=newff(PR,[S1 S2...SN],{TF1 TF2... TFN},BTF,BLF,PF)

PR:一个R×2矩阵, 由R维输入向量的每维最小值和最大值组成

Si:第i层的神经元个数

TFi:第i层的传递函数,默认为tansig

BTF:训练函数,默认为trainlm

BLF:学习函数,默认为learngdm

PF:性能函数,默认为mse

net=newff([0,10;1,2],[5,1],{‘tansig’,’purelin’},’trainlm’);

%生成一个两层BP网络,隐层和输出层神经的个数为5和1,传递函数分别为tansig和purelin,训练函数为trainlm,其他默认

lBPNN的初始化:函数init

newff 函数在建立网络对象的同时, 自动调用初始化函数, 根据缺省的参数设置网络的连接权值和阈值.

使用函数init可以对网络进行自定义的初始化. 通过选择初始化函数, 可对各层连接权值和阈值分别进行不同的初始化.
lBPNN的训练:函数train

利用已知的“输入——目标”样本向量数据对网络进行训练,采用train函数完成。训练之前,对训练参数进行设置:

net  = train(net,P,T)
训练参数参数含义默认值
net.trainParam.epochs训练步数100
net.trainParam.show显示训练结果的间隔步数25
net.trainParam.goal训练目标误差0
net.trainParam.time训练允许时间INF
net.trainParam.lr学习率0.01

BPNN的训练:学习算法的选择

matlab神经网络工具箱对常规的BP算法进行改进,提供了一系列快速算法,以满足不同问题的需要

学习算法适用问题类型收敛性能占用存储空间其他特点
trainlm函数拟合收敛快,误差小性能随网络规模增大而变差
trainrp模式分类收敛最快较小性能随着网络训练误差减小而变差
trainscg函数拟合与模式分类收敛较快性能稳定中等尤其适用于网络国模较大的情况
trainbfg函数拟合收敛较快较大计算量随着网络规模的增大呈几何增长
traingdx模式分类收敛较慢较小适用于提前停止的方法

BPNN的仿真或者测试:函数sim或net

A=sim(net,p)  %网络仿真
A=net(p)  %网络仿真    

4.1 一般步骤

数据归一化——mapminmax

创建BP网络——newff

初始化——init

训练算法——trainlm(速度快,需存储空间大)

学习规则——learngdm

网络训练——train

仿真——net,sim

BP神经网络实例

例:公路运量预测问题:公路运量主要包括公路的客运量和公路货运量两个方面。据研究,某地区的公路运量主要与该地区的人数、机动车数量和公路面积有关,表1给出了20年的公路运量相关数据,表中单位分别为万人/万量/万平方千米/万吨/万人。

根据有关部门数据,该地区2010年和2011年的人数分别为73.39和75.55万人,机动车数量分别为3.9635和4.0975万辆,公路面积将分别为0.9880和1.0268万平方米。

请利用BP神经网络预测该地区2010年2011年得公路客运量和公路货运量。

img

img

BP网络求解步骤:

1)原始数据的输入;

2)数据归一化;

3)网络建立以及训练;

4)对原始数据进行仿真;

5)将原始数据仿真的结果与已知样本进行对比;

6)对新数据进行仿真。

(1)原始数据的输入:

sqrts=[20.55 22.44  25.37  27.13  29.45  30.10  30.96  34.06  36.42   38.09  39.13  39.99  41.93  44.59  47.30  52.89  55.73  56.76  59.17  60.63];%人数(单位:万人)
sqjdcs=[0.6 0.75  0.85 0.91  1.05  1.35  1.45  1.6  1.7  1.85  2.15  2.2  2.25  2.35  2.5  2.6  2.7  2.85  2.95  3.1];%机动车数(单位:万辆)
sqglmj=[0.09  0.11  0.11  0.14  0.20  0.23  0.23  0.32  0.32  0.34  0.36  0.36  0.38  0.49  0.56  0.59  0.59  0.67  0.69  0.79];%公路面积
glkyl=[5126 6217  7730  9145  10460  11387   12353  15750  18304  19836  21024  19490  20433  22598   25107   33442   36836  40548  42927  43462]%公路客运量
glhyl=[1237  1379  1385  1399  1663  1714  1834  4322   8132  8936   11099  11203  10524  11115  13320  16762  18673   20724   20803  21804];%公路货运量
p=[sqrts;sqjdcs;sqglmj];%输入数据矩阵
t=[dlhyl;glhyl];%目标数据矩阵

(2)归一化:利用函数premnmx对数据做归一化处理:

[pn,minp,maxp,tn,mint,maxt]=premnmx(p,t);
dx=[-1,1;-1,1;-1,1];

(3)训练:利用处理好的数据对网络进行训练:

%BP网络训练
net=newff(dx,[3,2],{'tansig','tansig','purelin'},'traingdx');
net.trainParam.show=2000;              %显示训练结果的间隔步数
net.trainParam.Lr=0.05;             %学习率
net.trainParam.epochs=20000;       %训练步数
net.trainParam.goal=0.65*10^(-3);     %训练目标误差
net=train(net,pn,tn);
an=sim(net,pn);
a=postmnmx(an,mint,maxt);    
pnew=[73.39  75.55
      3.9635 4.0975
      0.9880 1.0268];
pnewn=tramnmx(pnew,minp,maxp);             
anewn=sim(net,pnewn);   
anew=postmnmx(anewn,mint,maxt);       

(4)用原始数据仿真的结果和已知数据进行对比:

x=1990:2009;
newk=a(1,:);
newh=a(2,:);
figure(2);
subplot(2,1,1);
plot(x,newk,'r-o',x,glkyl,'b--+');
legend('网络输出客运量','实际客运量');
xlabel('年份');ylabel('客运量/万人');
title('运用工具箱客运量学习和测试对比图');
hold on
plot([2010,2011],[anew(1,:)],'r-o');

subplot(2,1,2);plot(x,newh,'r-o',x,glhyl,'b--+');
legend('网络输出货运量','实际货运量');
xlabel('年份');
ylabel('货运量/万人');
title('运用工具箱货运量学习和测试对比图');
hold on
plot([2010,2011],[anew(2,:)],'r-o');

总程序如下:

sqrts=[20.55 22.44  25.37  27.13  29.45  30.10  30.96  34.06  36.42   38.09  39.13  39.99  41.93  44.59  47.30  52.89  55.73  56.76  59.17  60.63];%人数(单位:万人)
sqjdcs=[0.6 0.75  0.85 0.91  1.05  1.35  1.45  1.6  1.7  1.85  2.15  2.2  2.25  2.35  2.5  2.6  2.7  2.85  2.95  3.1];%机动车数(单位:万辆)
sqglmj=[0.09  0.11  0.11  0.14  0.20  0.23  0.23  0.32  0.32  0.34  0.36  0.36  0.38  0.49  0.56  0.59  0.59  0.67  0.69  0.79];%公路面积
glkyl=[5126 6217  7730  9145  10460  11387   12353  15750  18304  19836  21024  19490  20433  22598   25107   33442   36836  40548  42927  43462];%公路客运量
glhyl=[1237  1379  1385  1399  1663  1714  1834  4322   8132  8936   11099  11203  10524  11115  13320  16762  18673   20724   20803  21804];%公路货运量
p=[sqrts;sqjdcs;sqglmj];%输入数据矩阵
t=[glkyl;glhyl];%目标数据矩阵
[pn,minp,maxp,tn,mint,maxt]=premnmx(p,t);
dx=[-1,1;-1,1;-1,1];
net=newff(dx,[3,2],{'tansig','tansig','purelin'},'traingdx');
net.trainParam.show=2000;
net.trainParam.Lr=0.05;
net.trainParam.epochs=20000;
net.trainParam.goal=0.65*10^(-3);
net=train(net,pn,tn);
an=sim(net,pn);
a=postmnmx(an,mint,maxt);
pnew=[73.39 75.55
3.9635 4.0975
0.9880  1.0268];
pnewn=tramnmx(pnew,minp,maxp);
anewn=sim(net,pnewn);
anew=postmnmx(anewn,mint,maxt);
x=1990:2009;
newk=a(1,:);
newh=a(2,:);
figure(2);
subplot(2,1,1);
plot(x,newk,'r-o',x,glkyl,'b--+');
legend('网络输出客运量','实际客运量');
xlabel('年份');ylabel('客运量/万人');
title('运用工具箱客运量学习和测试对比图');
hold on
plot([2010,2011],[anew(1,:)],'r-o');
subplot(2,1,2);
plot(x,newh,'r-o',x,glhyl,'b--+');
legend('网络输出货运量','实际货运量');
xlabel('年份');
ylabel('货运量/万人');
title('运用工具箱货运量学习和测试对比图');
hold on
plot([2010,2011],[anew(2,:)],'r-o');
anew  %输出2010和2011年的公路客运量和货运量

得到结果:

img

img

img

也就是说:

2010年和2011年的公路客运量分别为44451万人和22058万人,2010年和2011年的公路货运量分别为44496万吨和22059万吨。

BPNN_title.jpg

Last modification:August 22nd, 2019 at 04:23 pm
如果觉得我的文章对你有用,请随意赞赏