BP神经网络(一)定义误差反向传播的BP算法简称BP算法,其基本思想是梯度下降法。
它采用梯度搜索技术,以期使网络的实际输出值与期望输出值的误差均方值为最小。
(二)BP网络特点1)是一种多层网络,包括输入层、隐含层和输出层;2)层与层之间采用全互连方式,同一层神经元之间不连接;3)权值通过δ学习算法进行调节;4)神经元激发函数为S函数;5)学习算法由正向传播和反向传播组成;6)层与层的连接是单向的,信息的传播是双向的。
(三)BP主要应用回归预测(可以进行拟合,数据处理分析,事物预测,控制等)、分类识别(进行类型划分,模式识别等),但无论那种网络,什么方法,解决问题的精确度都无法打到100%的,但并不影响其使用,因为现实中很多复杂的问题,精确的解释是毫无意义的,有意义的解析必定会损失精度。
(四)BP网络各种算法的应用范围1)Traingd:批梯度下降训练函数,沿网络性能参数的负梯度方向调整网络的权值和阈值;2)Traingdm:动量批梯度下降函数,也是一种批处理的前馈神经网络训练方法,不但具有更快的收敛速度,而且引入了一个动量项,有效避免了局部最小问题在网络训练中出现;3)Trainrp:有弹回的BP算法,用于消除梯度模值对网络训练带来的影响,提高训练的速度(主要通过delt_inc和delt_dec来实现权值的改变);4)Trainlm:Levenberg-Marquardt算法,对于中等规模的BP神经网络有最快的收敛速度,是系统默认的算法.由于其避免了直接计算赫赛矩阵,从而减少了训练中的计算量,但需要较大内存量.;5)traincgb:Plwell-Beale算法:通过判断前后梯度的正交性来决定权值和阈值的调整方向是否回到负梯度方向上来;6)trainscg:比例共轭梯度算法:将模值信赖域算法与共轭梯度算法结合起来,减少用于调整方向时搜索网络的时间。
一般来说,traingd和traingdm是普通训练函数,而traingda,traingdx,traingd,trainrp,traincgf,traincgb,trainsc g,trainbgf等等都是快速训练函数.总体感觉就是训练时间的差别比较大,还带有精度的差异。
(五)实例及其仿真分析(BP网络底层代码的实现)1)程序%% 读入数据xlsfile='student.xls';[data,label]=getdata(xlsfile);%% 划分数据[traind,trainl,testd,testl]=divide(data,label);%% 设置参数rng('default')rng(0)nTrainNum = 60; % 60个训练样本nSampDim = 2; % 样本是2维的%% 构造网络net.nIn=2;net.nHidden = 3; % 3个隐含层节点net.nOut = 1; % 一个输出层节点w = 2*(rand(net.nHidden,net.nIn)-1/2); % nHidden * 3 一行代表一个隐含层节点b = 2*(rand(net.nHidden,1)-1/2);net.w1 = [w,b];W = 2*(rand(net.nOut,net.nHidden)-1/2);B = 2*(rand(net.nOut,1)-1/2);net.w2 = [W,B];%% 训练数据归一化mm=mean(traind);% 均值平移fori=1:2traind_s(:,i)=traind(:,i)-mm(i);end% 方差标准化ml(1) = std(traind_s(:,1));ml(2) = std(traind_s(:,2));fori=1:2traind_s(:,i)=traind_s(:,i)/ml(i);end%% 训练SampInEx = [traind_s';ones(1,nTrainNum)]; expectedOut=trainl;eb = 0.01; % 误差容限eta = 0.6; % 学习率mc = 0.8; % 动量因子maxiter = 2000; % 最大迭代次数iteration = 0; % 第一代errRec = zeros(1,maxiter);outRec = zeros(nTrainNum, maxiter);NET=[]; % 记录% 开始迭代fori = 1 : maxiterhid_input = net.w1 * SampInEx; % 隐含层的输入hid_out = logsig(hid_input); % 隐含层的输出ou_input1 = [hid_out;ones(1,nTrainNum)]; % 输出层的输入ou_input2 = net.w2 * ou_input1;out_out = logsig(ou_input2); % 输出层的输出outRec(:,i) = out_out'; % 记录每次迭代的输出err = expectedOut - out_out; % 误差sse = sumsqr(err);errRec(i) = sse; % 保存误差值fprintf('第%d 次迭代误差: %f\n', i, sse);iteration = iteration + 1;% 判断是否收敛ifsse<=ebbreak;end% 误差反向传播% 隐含层与输出层之间的局部梯度DELTA = err.*dlogsig(ou_input2,out_out);% 输入层与隐含层之间的局部梯度delta = net.w2(:,1:end-1)' * DELTA.*dlogsig(hid_input,hid_out);% 权值修改量dWEX = DELTA*ou_input1';dwex = delta*SampInEx';% 修改权值,如果不是第一次修改,则使用动量因子ifi == 1net.w2 = net.w2 + eta * dWEX;net.w1 = net.w1 + eta * dwex;elsenet.w2 = net.w2 + (1 - mc)*eta*dWEX + mc * dWEXOld;net.w1 = net.w1 + (1 - mc)*eta*dwex + mc * dwexOld; end% 记录上一次的权值修改量dWEXOld = dWEX;dwexOld = dwex;end%% 测试% 测试数据归一化fori=1:2testd_s(:,i)=testd(:,i)-mm(i);endfori=1:2testd_s(:,i)=testd_s(:,i)/ml(i);end% 计算测试输出InEx=[testd_s';ones(1,260-nTrainNum)];hid_input = net.w1 * InEx;hid_out = logsig(hid_input); % output of the hidden layer nodes ou_input1 = [hid_out;ones(1,260-nTrainNum)];ou_input2 = net.w2 * ou_input1;out_out = logsig(ou_input2);out_out1=out_out;% 取整out_out(out_out<0.5)=0;out_out(out_out>=0.5)=1;% 正确率rate = sum(out_out == testl)/length(out_out);%% 显示% 显示训练样本train_m = traind(trainl==1,:);train_m=train_m';train_f = traind(trainl==0,:);train_f=train_f';figure(1)plot(train_m(1,:),train_m(2,:),'bo');hold on;plot(train_f(1,:),train_f(2,:),'r*');xlabel('身高')ylabel('体重')title('训练样本分布')legend('男生','女生')figure(2)axis onhold ongrid[nRow,nCol] = size(errRec);plot(1:nCol,errRec,'LineWidth',1.5);legend('误差平方和');xlabel('迭代次数','FontName','Times','FontSize',10);ylabel('误差');% 正确率:87%%将样本逐个输入,由于样本输入的随机性,可以在一定程度上避免出现局部最优。
%% 清理clear allclc%% 读入数据xlsfile='student.xls';[data,label]=getdata(xlsfile);%% 划分数据[traind,trainl,testd,testl]=divide(data,label);%% 设置参数rng('default')rng(0)nTrainNum = 60; % 60个训练样本nSampDim = 2; % 样本是2维的M=2000; % 迭代次数ita=0.1; % 学习率alpha=0.2;%% 构造网络HN=3; % 隐含层层数net.w1=rand(3,HN);net.w2=rand(HN+1,1);%% 归一化数据mm=mean(traind);fori=1:2traind_s(:,i)=traind(:,i)-mm(i);endml(1) = std(traind_s(:,1));ml(2) = std(traind_s(:,2));fori=1:2traind_s(:,i)=traind_s(:,i)/ml(i);end%% 训练for x=1:M % 迭代ind=randi(60); % 从1-60中选一个随机数in=[traind_s(ind,:),1]; % 输入层输出net1_in=in*net.w1; % 隐含层输入net1_out=logsig(net1_in); % 隐含层输出net2_int = [net1_out,1]; % 下一次输入net2_in = net2_int*net.w2; % 输出层输入net2_out = logsig(net2_in); % 输出层输出err=trainl(ind)-net2_out; % 误差errt(x)=1/2*sqrt(sum(err.^2)); % 误差平方fprintf('第%d 次循环,第%d个学生,误差 %f\n',x,ind, errt(x));% 调整权值fori=1:length(net1_out)+1for j=1:1ipu1(j)=err(j); % 局部梯度% 输出层与隐含层之间的调整量delta1(i,j) = ita.*ipu1(j).*net2_int(i);endendfor m=1:3fori=1:length(net1_out)% 局部梯度ipu2(i)=net1_out(i).*(1-net1_out(i)).*sum(ipu1.*net.w2);% 输入层和隐含层之间的调整量delta2(m,i)= ita.*in(m).*ipu2(i);endend% 调整权值if x==1net.w1 = net.w1+delta2;net.w2 = net.w2+delta1;elsenet.w1 = net.w1+delta2*(1-alpha) + alpha*old_delta2;net.w2 = net.w2+delta1*(1-alpha) + alpha*old_delta1;endold_delta1=delta1;old_delta2=delta2;end%% 测试% 测试数据归一化fori=1:2testd_s(:,i)=testd(:,i)-mm(i);endfori=1:2testd_s(:,i)=testd_s(:,i)/ml(i);endtestd_s = [testd_s,ones(length(testd_s),1)];net1_in=testd_s*net.w1;net1_out=logsig(net1_in);net1_out=[net1_out,ones(length(net1_out),1)]; net2_int = net1_out;net2_in = net2_int*net.w2;net2_out=net2_in;% 取整net2_out(net2_out<0.5)=0;net2_out(net2_out>=0.5)=1;rate=sum(net2_out==testl')/length(net2_out); %% 显示figure(1);plot(1:M,errt,'b-','LineWidth',1.5);xlabel('迭代次数')ylabel('误差')title('BP网络串行训练的误差')% 正确率:88.5%2)仿真结果。