BP算法实现
简单的实现了一下经典的BP算法的核心代码,目的是为了加深一下对此算法的理解便于下一步的深入学习。参考了其程序 对BP算法进行理论推导,对其梯度下降、反向传播有了一定的理解,但一部分公式并未推导通;理解了学习率,步长的基础概念,但对于激发函数的意义、如何选激发函数还是不太理解。
背景
1986 年,Rumelhart、Hinton 和 Williams 联合 在《自然》杂志发表了著名的反向传播算法(BP),首次阐述了 BP 算法在浅层前向型神经网络模型的应用,不但明显降低了最优化问题求解的运算量,还通过增加一个隐层解决了感知器无法解决的 XOR Gate 难题,该算法成为神经网络的最基本算法。从此,神经网络的研究与应用开始复苏。
BP算法的实现步骤
程序流程图
代码实现
clc;clear all;
%准备好训练集
%人数(单位:万人)
numberOfPeople=[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];
%机动车数(单位:万辆)
numberOfAutomobile=[0.6 0.75 0.85 0.9 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];
%公路面积(单位:万平方公里)
roadArea=[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];
%公路客运量(单位:万人)
passengerVolume = [5126 6217 7730 9145 10460 11387 12353 15750 18304 19836 21024 19490 20433 22598 25107 33442 36836 40548 42927 43462];
%公路货运量(单位:万吨)
freightVolume = [1237 1379 1385 1399 1663 1714 1834 4322 8132 8936 11099 11203 10524 11115 13320 16762 18673 20724 20803 21804];
i=3;%输入数据维度
j=8;%隐藏层神经元数量
k=2;%输出数据维度
SampleNum=20;%样本数量
%输入数据矩阵
input = [numberOfPeople; numberOfAutomobile; roadArea];
%目标(输出)数据矩阵
output = [passengerVolume; freightVolume];
%对训练集中的输入数据矩阵和目标数据矩阵进行归一化处理
[sampleInput, minp, maxp, tmp, mint, maxt] = premnmx(input, output);
%噪声强度
noiseIntensity = 0.01;
%利用正态分布产生噪声
noise = noiseIntensity * randn(k, SampleNum);
%给样本输出矩阵tmp添加噪声,防止网络过度拟合
sampleOutput = tmp + noise;
W1=rand([j i]);%j个神经元 隐藏层权重系数
W2=rand([k j]);%k个输出 输出层权重系数
Theta1=rand([j,1]);%隐藏层阈值
Theta2=rand([k,1]);%输出层层阈值
dW1=zeros(j,i);%隐藏层权重系数修正量
dW2=zeros(k,j);%输出层权重系数修正量
dTheta1=zeros([j,1]);%隐藏层阈值修正量
dTheta2=zeros([k,1]);%输出层层阈值修正量
Alpha=0.9;%权系数修正常数,一般区0.7-0.9左右,目的是为了加速收敛
LearnRate=0.035;%学习速率,即步长,一般在0-1之间。
error0 = 0.65*10^(-3);%训练网络所要达到的目标误差
maxEpochs = 50000;%最大训练次数
errorHistory = [];%保存能量函数(误差平方和)的历史记录
for n = 1:maxEpochs
for element=1:SampleNum
X0=sampleInput(:,element);
Y=sampleOutput(:,element);
X1=f([W1 Theta1]*[X0;1]);%隐藏层的输出
X2=f([W2 Theta2]*[X1;1]);%输出
%反向传播
d2=X2.*(1-X2).*(X2-Y);%输出层学习误差
d1=X1.*(1-X1).*(W2'*d2);%学习误差反向传播
dTheta2=-LearnRate*d2.*ones(k,1)+Alpha*dTheta2;%计算修正阈值
dTheta1=-LearnRate*d1.*ones(j,1)+Alpha*dTheta1;
dW2=-LearnRate*d2*X1'+Alpha*dW2;%计算修正权系数(需用到上次的修正量)
dW1=-LearnRate*d1*X0'+Alpha*dW1;
W2=W2+dW2;
W1=W1+dW1;
Theta2=Theta2+dTheta2;
Theta1=Theta1+dTheta1;
end
E = sumsqr(Y-X2);%能量平方差
errorHistory = [errorHistory E];%保存历史便于观察
if E < error0
break;%误差满足要求满足便退出
end
end
plot(errorHistory(1:100));
function y=f(x)
%Sigmoid函数
y=1./(1+exp(-x));
end
%参考程序
[1]刘彩红. BP神经网络学习算法的研究[D].重庆师范大学,2008.