BP神经网络简单代码分析

BP神经网络的构建

BP网是一种前馈多层(一般都选用3层)网络。理论已经证明一个三层网络可以无限近似任意连续函数。

在进入代码前,我们需先认识这些有关神经网络的函数:

  • newff()函数:建立一个可训练的前馈网络。
  • sim()函数:运行仿真。
  • init()函数:初始化神经网络,根据最新的网络初始化函数返回神经网络的权值和误差。
  • sign()函数:符号函数,sign(整数)=1;sign(负数)=-1;sign(0)=0。
  • tansig()函数: 神经网络层传递函数,将神经网络层的净输入转换为净输出。
  • purelin()函数:神经网络层传递函数。
  • newp()函数:构造感知器模型。
  • errsurf()函数:单输入神经元的误差面。
  • plotes()函数:用来绘制二维图像。
  • train()函数:对神经网络进行训练,会弹出窗体。
    在这里插入图片描述

在了解这些基础函数的基础上,我们来看一个构建BP神经网络的matlab代码:

% BP网络
% BP神经网络的构建
net=newff([-1 2;0 5],[3,1],{'tansig','purelin'},'traingd')
%newff([-1 2;0 5],[3,1],{'tansig','purelin'},'traingd')建立一个可训练的前馈网络
%创建一个二层网络,它的输入是两个元素的向量,输入向量的第一个元素的范围是[-1 2],输入向量的第二个元素的范围是[0 5]%第一层有三个神经元,第二层有一个神经元。
%第一层的传递函数是tansig(正切S型传递函数),输出层的传递函数是purelin(线性传递函数)。训练函数是traingd(最速下降BP算法)。
%net.IW{1}	%输入层到隐含层的权重
%net.b{1}	%输入层的阈值

p=[1;2];	%p为网络输入
a=sim(net,p)	%sim()函数对于神经网络进行仿真,返回输出
net=init(net);	%init(net)根据最新的网络初始化函数返回神经网络的权值和误差,此时new.IW{1}、net.b{1}的值已改变
a=sim(net,p)

p2=net.IW{1}*p+net.b{1}	%p2为隐含层的输入
a2=sign(p2)	%符号函数
a3=tansig(a2)	%神经网络层传递函数:将神经网络层的净输入转换为净输出
a4=purelin(a3)	%线性传递函数:输入与输出值可取任意值,输入值=输出值

net.b{2}	%隐含层的阈值
net.b{1}	%输入层的阈值

net.IW{1}	%输入层到隐含层的权重
net.IW{2}	%隐含层到输出层的权重
0.7616+net.b{2}
a-net.b{2}
(a-net.b{2})/ 0.7616

p1=[0;0];	%改变网络输入
a5=sim(net,p1)
net.b{2}


% BP网络
% BP神经网络的构建
net=newff([-1 2;0 5],[3,1],{'tansig','purelin'},'traingd')
p=[1;2];
a=sim(net,p)
net=init(net);
a=sim(net,p)
p2=net.IW{1}*p+net.b{1}
a2=sign(p2)
a3=tansig(a2)
a4=purelin(a3)
net.b{2}
net.b{1}

P=[1.2;3;0.5;1.6]
W=[0.3 0.6 0.1 0.8]
net1=newp([0 2;0 2;0 2;0 2],1,'purelin');
net2=newp([0 2;0 2;0 2;0 2],1,'logsig');
net3=newp([0 2;0 2;0 2;0 2],1,'tansig');
net4=newp([0 2;0 2;0 2;0 2],1,'hardlim');

net1.IW{1}=W;
net2.IW{1}=W;
net3.IW{1}=W;
net4.IW{1}=W;

a1=sim(net1,P)
a2=sim(net2,P)
a3=sim(net3,P)
a4=sim(net4,P)

init(net1);
net1.b{1}

% 训练
p=[-0.1 0.5]
t=[-0.3 0.4]
w_range=-2:0.4:2;
b_range=-2:0.4:2;
ES=errsurf(p,t,w_range,b_range,'logsig');	%单输入神经元的误差曲面
plotes(w_range,b_range,ES)	%绘制单输入神经元的误差曲面
hold off;
net=newp([-2,2],1,'logsig');
net.trainparam.epochs=100;	%训练次数设置为100次
net.trainparam.goal=0.001;	%训练目标最小误差设置为0.001
figure(2);
subplot(1,2,1);
[net,tr]=train(net,p,t);	%神经网络训练函数
title('动态逼近')
wight=net.iw{1}
bias=net.b
hold on;

% 练
p=[-0.2 0.2 0.3 0.4]
t=[-0.9 -0.2 1.2 2.0]
h1=figure(1);
net=newff([-2,2],[5,1],{'tansig','purelin'},'trainlm');
net.trainparam.epochs=100;
net.trainparam.goal=0.0001;
net=train(net,p,t);
a1=sim(net,p)

h2=figure(2);
subplot(1,2,2);
plot(p,t,'*');
title('样本')
xlabel('Input');
ylabel('Output');

hold on;
ptest1=[0.2 0.1]
ptest2=[0.2 0.1 0.9]
a1=sim(net,ptest1);
a2=sim(net,ptest2);

运行结果如下:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

train()函数得到的两个窗体:

  1. 窗体一:由Neural Network处可知,这是一个一层的网络,由一个神经元组成,输入与输出均为1。在Algorithms处描述了本神经网络的一些算法–Trainning:训练的算法,采用的是LM算法(列文伯格-马夸尔特法),Performance:性能检测算法,采用的是mse(均方误差)。在Progress下面,显示了当前的训练状态: Epoch–训练次数100次,Time:训练时间,Performance:均方误差为0.242。在Plots下面,有2个按键,分别用于绘制当前神经网络的性能图和训练状态。
  2. 窗体二:由Neural Network处可知,这是一个二层的网络,分别由五个神经元和一个神经元组成,输入与输出均为1。在Algorithms处描述了本神经网络的一些算法–Trainning:训练的算法,采用的是LM算法(列文伯格-马夸尔特法),Performance:性能检测算法,采用的是mse(均方误差)。在Progress下面,显示了当前的训练状态: Epoch–训练次数14次,Time:训练时间,Performance:均方误差为4.70e-09,Gradiengt:梯度值为1.00e-06,Validation Checks:校验检查。在Plots下面,有3个按键,分别用于绘制当前神经网络的性能图、训练状态和回归分析。

感知器

感知器神经网络的构建

% 1. 感知器神经网络的构建
% 1.1  生成网络
net=newp([0 2],1);	%单输入,输入值为[0,2]之间的数
inputweights=net.inputweights{1,1};	%第一层的权重为1
biases=net.biases{1};	%阈值为1

% 1.2  网络仿真
net=newp([-2 2;-2 2],1);%	新建net对象,是一个感知器,有两个输入,一个神经元,默认二值激活,范围都是-22,一层
net.IW{1,1}=[-1 1];	%权重,net.IW{i,j}表示第i层网络第j个神经元的权重向量
net.IW{1,1}	%输出
net.b{1}=1;	%输入层的阈值
net.b{1}
p1=[1;1],a1=sim(net,p1)	%sim()函数对于神经网络进行仿真,返回输出
p2=[1;-1],a2=sim(net,p2)
p3={[1;1] [1 ;-1]},a3=sim(net,p3)	%两组数据放一起
p4=[1 1;1 -1],a4=sim(net,p4)	%也可以放在矩阵里面
net.IW{1,1}=[3,4];
net.b{1}=[1];
a1=sim(net,p1)

% 1.3  网络初始化
net=init(net);	%利用init函数将网络输入的权值和阈值改变为随机数
wts=net.IW{1,1}
bias=net.b{1}
% 改变权值和阈值为随机数
net.inputweights{1,1}.initFcn='rands';
net.biases{1}.initFcn='rands';
net=init(net);
%init(net)根据最新的网络初始化函数返回神经网络的权值和误差,其结果由net.initFcn和参数值net.initparam影响。
bias=net.b{1}
wts=net.IW{1,1}
a1=sim(net,p1)

感知器神经网络的学习和训练

% 2. 感知器神经网络的学习和训练
% 1 网络学习
net=newp([-2 2;-2 2],1);
net.b{1}=[0];
w=[1 -0.8]
net.IW{1,1}=w;
p=[1;2];
t=[1];
a=sim(net,p)
e=t-a
dw=learnp(w,p,[],[],[],[],e,[],[],[],[],[])	%感知器权重和偏差学习功能
%learnp根据感知器学习规则从神经元的输入P和误差E计算给定神经元的权重变化dW
w=w+dw
net.IW{1,1}=w;
a=sim(net,p)
net = newp([0 1; -2 2],1);
P = [0 0 1 1; 0 1 0 1];
T = [0 1 1 1];
Y = sim(net,P)
net.trainParam.epochs = 20;	%训练次数设置为20次
net = train(net,P,T);	%神经网络训练函数
Y = sim(net,P)

% 2 网络训练
net=init(net);
p1=[2;2];t1=0;p2=[1;-2];t2=1;p3=[-2;2];t3=0;p4=[-1;1];t4=1;
net.trainParam.epochs=1;	%训练次数设置为1次
net=train(net,p1,t1)
w=net.IW{1,1}
b=net.b{1}
a=sim(net,p1)
net=init(net);
p=[[2;2] [1;-2] [-2;2] [-1;1]];
t=[0 1 0 1];
net.trainParam.epochs=1;
net=train(net,p,t);
a=sim(net,p)
net=init(net);
net.trainParam.epochs=2;
net=train(net,p,t);
a=sim(net,p)
net=init(net);
net.trainParam.epochs=20;
net=train(net,p,t);
a=sim(net,p)

% 3. 二输入感知器分类可视化问题
P=[-0.5 1 0.5 -0.1;-0.5 1 -0.5 1];
T=[1 1 0 1]
net=newp([-1 1;-1 1],1);
plotpv(P,T);	%绘制样本点,可在坐标图中绘出给定的样本点及其类别,不同的类别使用不同的符号
plotpc(net.IW{1,1},net.b{1});
net=adapt(net,P,T);	%用来在线学习(增量学习)
net.IW{1,1}
net.b{1}
plotpv(P,T);
plotpc(net.IW{1,1},net.b{1})
net.adaptParam.passes=3;	%决定在训练过程中重复次数为3次
net=adapt(net,P,T);
net.IW{1,1}
net.b{1}
plotpc(net.IW{1},net.b{1})
net.adaptParam.passes=6;
net=adapt(net,P,T)
net.IW{1,1}
net.b{1}
plotpv(P,T);
plotpc(net.IW{1},net.b{1})
plotpc(net.IW{1},net.b{1})

%仿真
a=sim(net,p);
plotpv(p,a)

p=[0.7;1.2]
a=sim(net,p);
plotpv(p,a);
hold on;
plotpv(P,T);
plotpc(net.IW{1},net.b{1})
%感知器能够正确分类,从而网络可行。

% 4. 标准化学习规则训练奇异样本
P=[-0.5 -0.5 0.3 -0.1 -40;-0.5 0.5 -0.5 1.0 50]
T=[1 1 0 0 1];
net=newp([-40 1;-1 50],1);
plotpv(P,T);	%标出所有点
hold on;
linehandle=plotpc(net.IW{1},net.b{1});	%画出分类线
E=1;
net.adaptParam.passes=3;	%passes决定在训练过程中训练值重复的次数。
while (sse(E))	%求网络误差平方和
    [net,Y,E]=adapt(net,P,T);
    linehandle=plotpc(net.IW{1},net.b{1},linehandle);
    drawnow;
end;
axis([-2 2 -2 2]);
net.IW{1}
net.b{1}

%另外一种网络修正学习(非标准化学习规则learnp)
hold off;
net=init(net);
net.adaptParam.passes=3;
net=adapt(net,P,T);
plotpc(net.IW{1},net.b{1});
axis([-2 2 -2 2]);	%设置当前所绘图像的x轴和y轴的范围
net.IW{1}
net.b{1}
%无法正确分类
%标准化学习规则网络训练速度要快!

% 训练奇异样本
% 用标准化感知器学习规则(标准化学习数learnpn)进行分类
net=newp([-40 1;-1 50],1,'hardlim','learnpn');
plotpv(P,T);
linehandle=plotpc(net.IW{1},net.b{1});
e=1;
net.adaptParam.passes=3;
net=init(net);
linehandle=plotpc(net.IW{1},net.b{1});
while (sse(e))
[net,Y,e]=adapt(net,P,T);
linehandle=plotpc(net.IW{1},net.b{1},linehandle);
end;
axis([-2 2 -2 2]);
net.IW{1}	%权重
net.b{1}	%阈值
%正确分类
%非标准化感知器学习规则训练奇异样本的结果
net=newp([-40 1;-1 50],1);
net.trainParam.epochs=30;
net=train(net,P,T);
pause;
linehandle=plotpc(net.IW{1},net.b{1});
hold on;
plotpv(P,T);
linehandle=plotpc(net.IW{1},net.b{1});
axis([-2 2 -2 2]);

% 5. 设计多个感知器神经元解决分类问题
p=[1.0 1.2 2.0 -0.8; 2.0 0.9 -0.5 0.7]
t=[1 1 0 1;0 1 1 0]
plotpv(p,t);
hold on;
net=newp([-0.8 1.2; -0.5 2.0],2);
linehandle=plotpc(net.IW{1},net.b{1});
net=newp([-0.8 1.2; -0.5 2.0],2);
linehandle=plotpc(net.IW{1},net.b{1});
e=1;
net=init(net);
while (sse(e))
[net,y,e]=adapt(net,p,t);
linehandle=plotpc(net.IW{1},net.b{1},linehandle);
drawnow;
end;

最后运行结果如下:
在这里插入图片描述

在这里插入图片描述

这里的运行结果只粘贴最后一次的train()函数弹出的窗体:由Neural Network处可知,这是一个一层的网络,由一个神经元组成,输入为2,输出为1。在Algorithms处描述了本神经网络的一些算法–Trainning:训练的算法,采用的是Cyclical Weights/Bias Rule(感知器),Performance:性能检测算法,采用的是mae(平均绝对误差)。在Progress下面,显示了当前的训练状态: Epoch–训练次数30次,Time:训练时间,Performance:均方误差为0.400。在Plots下面,有2个按键,分别用于绘制当前神经网络的性能图和训练状态。

发布了13 篇原创文章 · 获赞 6 · 访问量 2295

猜你喜欢

转载自blog.csdn.net/weixin_44060222/article/details/102540660