BP神经网络介绍
BP(back propagation)神经网络是1986年由Rumelhart和McClelland为首的科学家提出的概念,是一种按照误差逆向传播算法训练的多层前馈神经网络,是应用最广泛的神经网络。
神经网络的基本结构如下:
给定一组样本,样本中有输入数据和输出数据。
神经网络通过各神经元的权值与阈值来对样本中的输入数据进行计算,得出一组输出,计算的输出数据与样本的输出数据必然存在误差,神经网络会通过梯度下降法利用这个误差逐层去向前修改神经元的权值和阈值,以得到减小误差的效果。
具体原理的推导
BP神经网络的功能
BP神经网络在数学建模中的主要功能如下:
- 函数逼近:用输入向量和相应的输出向量训练一个网络逼近一个函数,又可说是拟合
- 分类:把输入向量所定义的合适方式进行分类
通过对已知数据构建一个神经网络,我们就可以利用这个神经网络去做未知数据的预测。
BP神经网络的缺点
BP神经网络同时也存在以下缺点:
- 容易陷入局部极小值
- 网络层数、神经元个数的选择没有相应的理论指导
- 学习速度慢,即使是一个简单的问题,一般也需要几百次甚至上千次的学习才能收敛
- 实际问题的研究中,我们无法对得到的权值和阈值做出实际意义的解释
对于部分缺点,已经存在改良的方法。
BP神经网络在matlab中的使用
matlab较好的实现了BP神经网络,我们不再需要从头去写一个神经网络的代码。
接下来分别介绍拟合与分类的简单实例。
拟合实例
给定一个x的取值区间和相应的y值,用BP神经网络来拟合这个函数。
%% 制造数据
X=[1:0.01:10];
Y=X.^2+2*X+1;
%% 标准化
[XX,xps]=mapminmax(X);
[YY,yps]=mapminmax(Y);
%% 建立并训练网络
x = XX;
t = YY;
% 选择训练函数
trainFcn = 'trainlm'; % Levenberg-Marquardt backpropagation.
% 建立网络
hiddenLayerSize = 10; % 隐含层神经元个数
net = fitnet(hiddenLayerSize,trainFcn);
% 将数据划分为三个集合,training(训练),validation(验证),test(测试)
net.divideFcn = 'dividerand'; % 数据随机划分
net.divideMode = 'sample'; % 针对单个数据
net.divideParam.trainRatio = 70/100; % training 70%
net.divideParam.valRatio = 15/100; % validation 15%
net.divideParam.testRatio = 15/100; % test 15%
% 选择网络的性能评估指标
net.performFcn = 'mse'; % 均方误差
% 开始训练
[net,tr] = train(net,x,t);
% Test the Network
y = net(x);
e = gsubtract(t,y);
performance = perform(net,t,y);
% View the Network
view(net)
%% 预测
XXX=[3.333333 6.666666 15];
XXX=mapminmax('apply',XXX,xps);
YYY=net(XXX);
YYY=mapminmax('reverse',YYY,yps)
%% 相关图像
% Plots
% Uncomment these lines to enable various plots.
% figure, plotperform(tr)
% figure, plottrainstate(tr)
% figure, ploterrhist(e)
% figure, plotregression(t,y)
% figure, plotfit(net,x,t)
分类实例
一个数字,1~10为类别1,11~20为类别2,21~30为类别3。
对于该数字的类别用一个向量来表示:
数字属于哪个类别,对于的x值为1,其余值为0。
之后直接按照拟合实例的操作对样本进行拟合,output有三个,为$x_1\ x_2\ x_3$。
因此分类问题就是将类别解析成一个向量,对向量的每一个元素进行拟合即可。
本例较为简单,但对于复杂问题依然可以采用这种处理方法。
%% 制造数据
A=[1:0.1:10];
B=[11:0.1:20];
C=[21:0.1:30];
X=[A B C];
Y=zeros(3,size(X,2));
for ii=1:size(X,2)
if X(ii)<=10
Y(1,ii)=1;
elseif X(ii)<=20
Y(2,ii)=1;
else
Y(3,ii)=1;
end
end
%% 标准化
[XX,xps]=mapminmax(X);
[YY,yps]=mapminmax(Y);
%% 建立并训练网络
x = XX;
t = YY;
% 选择训练函数
trainFcn = 'trainlm'; % Levenberg-Marquardt backpropagation.
% 建立网络
hiddenLayerSize = 10; % 隐含层神经元个数
net = fitnet(hiddenLayerSize,trainFcn);
% 将数据划分为三个集合,training(训练),validation(验证),test(测试)
net.divideFcn = 'dividerand'; % 数据随机划分
net.divideMode = 'sample'; % 针对单个数据
net.divideParam.trainRatio = 70/100; % training 70%
net.divideParam.valRatio = 15/100; % validation 15%
net.divideParam.testRatio = 15/100; % test 15%
% 选择网络的性能评估指标
net.performFcn = 'mse'; % 均方误差
% 开始训练
[net,tr] = train(net,x,t);
% 测试网络
y = net(x);
e = gsubtract(t,y);
performance = perform(net,t,y)
% 展示网络结构
view(net)
%% 预测
XXX=[5.3,15.976,27.8865];
XXX=mapminmax('apply',XXX,xps);
YYY=net(XXX);
YYY=mapminmax('reverse',YYY,yps)
%% 相关图像
% Plots
% Uncomment these lines to enable various plots.
%figure, plotperform(tr)
%figure, plottrainstate(tr)
%figure, ploterrhist(e)
%figure, plotregression(t,y)
%figure, plotfit(net,x,t)
matlab中对数据集的划分
神经网络有一个缺点就是过拟合(就是对训练数据过分拟合,所以偏离了其他未参加训练的数据)。
为防止过拟合,MATLAB采用的方法是把数据划分成三份,training(训练),validation(验证),test(测试)。
只有training数据参加训练,其他两部分数据不参加训练,用于检验。训练进行时,目标和训练(test)数据目标之间的误差会越来越小(因为网络就是根据这些数据训练的),刚开始时validation和validation目标之间的误差也会变小,可随着训练的增加,test的误差继续变小,validation的误差反而会有所上升。当validation的误差连续上升6次时(默认设置)训练就停止了(因为这时有过拟合的倾向)。
在训练时,用training训练,每训练一次,系统自动会将validation set中的样本数据输入神经网络进行验证,在validation set输入后会得出一个误差(不是网络的训练误差,而是验证样本数据输入后得到的输出误差,可能是均方误差),而此前对validation set会设置一个步数,比如默认是6echo,则系统判断这个误差是否在连续6次检验后不下降,如果不下降或者甚至上升,说明training set训练的误差已经不再减小,没有更好的效果了,这时再训练就没必要了,就停止训练,不然可能陷入过学习。