%% BP神经网络
clc,clear;
%% 输入
%% 第一类 分类器
% p为列向量
% d为列向量
% p=[0 0;0 1;1 0;1 1;]';
% d=[0;1;1;0];
%% 第二类 拟合sin曲线
% p=(-5:0.01:5);
% d=1+sin(pi/4*p)';
% p=p./abs(max(p));
% d=d./abs(max(d));
%% 第二类 拟合二次曲线
% p=(-5:0.01:5);
% d=p.^2';
% p=p./abs(max(p));
% d=d./abs(max(d));
%% 第三类 拟合代替插值
load('wx.mat')
Ma=Ma./abs(max(Ma));
xalpha=xalpha./abs(max(xalpha));
MY_WX0=MY_WX0./abs(max(max(MY_WX0)));
p=[repmat(xalpha,1,6);Ma(1)*ones(1,13),...
Ma(2)*ones(1,13),...
Ma(3)*ones(1,13),...
Ma(4)*ones(1,13),...
Ma(5)*ones(1,13),...
Ma(6)*ones(1,13);];
d=[MY_WX0(:,1);MY_WX0(:,2);MY_WX0(:,3);MY_WX0(:,4);MY_WX0(:,5);MY_WX0(:,6)];
%% 首先确定单个输入输出的维数
In_num=2;
Out_num=1;
e=0.1; %学习率
step=4e4; %迭代步数
%% 确定神经元层数
num_layers=3;
% 确定每层神经元的个数 并声明权值向量个数
nn=[4,5,1];
%%
W=cell(1,num_layers);
b=cell(1,num_layers);
n=cell(1,num_layers);
a=cell(1,num_layers);
s=cell(1,num_layers);
OUT=zeros(size(d));
for i=1:num_layers
if i==1
W{i}=rand(nn(i),In_num);
b{i}=rand(nn(i),1);
elseif i~=1 && i~=num_layers
W{i}=rand(nn(i),nn(i-1));
b{i}=rand(nn(i),1);
else W{i}=rand(Out_num,nn(i-1));
b{i}=rand(Out_num,1);
end
end
% 激励函数确定
f1=@(x)1./(1+exp(-x));
df1=@(x)(1./(1+exp(-x))).*(1-1./(1+exp(-x)));
fn=@(x)x;
dfn=@(x)1;
%% 迭代
for ii=1:step
%% 第一步 前向传播
j=fix(length(d)*rand(1)+1);
for k=1:num_layers
if k==1
n{k}=W{k}*p(:,j)+b{k};
a{k}=f1(n{k});
elseif k==num_layers
n{k}=W{k}*a{k-1}+b{k};
a{k}=fn(n{k});
else n{k}=W{k}*a{k-1}+b{k};
a{k}=f1(n{k});
end
end
%% 第二步 反向传播 计算灵敏度
k=num_layers;
while k>=1
if k==num_layers
% dF2=diag(df1(n{k}));%S
% s{k}=-2*dF2.*(d(j)-a{k});%S
dF2=1;%线性
s{k}=-2*dF2.*(d(j)-a{k});
else dF1=diag(df1(n{k}));
s{k}=dF1*(W{k+1})'*s{k+1};
end
k=k-1;
end
%% 第三步 调整权值
ee=zeros(1,1);%更新绝对值
for k=1:num_layers
if k==1
W{k}=W{k}-e.*s{k}*p(:,j)';
b{k}=b{k}-e.*s{k};
ee(k)=sum(sum(abs(e.*s{k}*p(:,j)')))+sum(abs(e.*s{k}));
elseif k>1 && k<=num_layers
W{k}=W{k}-e.*s{k}*a{k-1}';
b{k}=b{k}-e.*s{k};
ee(k)=sum(sum(abs(e.*s{k}*a{k-1}')))+sum(sum(abs(e.*s{k})));
end
end
%% 第四步 判断误差终止
if sum(ee)<1e-8
break
end
end
%% 输出测试
shuchu=cell(1,length(d));
for i=1:length(d)
for k=1:num_layers
if k==1
n{k}=W{k}*p(:,i)+b{k};
a{k}=f1(n{k});
elseif k==num_layers
n{k}=W{k}*a{k-1}+b{k};
a{k}=fn(n{k});
else
n{k}=W{k}*a{k-1}+b{k};
a{k}=f1(n{k});
end
shuchu{i}=a{k};
end
end
% for i=1:length(d)
% n1=W1*p(:,i)+b1;
% a1=f1(n1);
% n2=W2*a1+b2;
% shuchu(:,i)=f2(n2);
% end
% disp('实际值')
% disp(d)
% disp('学习值')
% disp(shuchu)
for i=1:length(d)
OUT(i)=shuchu{i};
end
error=sum(abs(d-OUT));
figure
plot(d,'LineStyle',':','LineWidth',1.5,'Color','k')
hold on
plot(OUT,'LineStyle','-','LineWidth',1.5,'Color','r')
legend('real','Bp')
title(['层数',num2str(num_layers),' 各层神经元数',num2str(nn),' 训练步数',num2str(ii),'步',' 误差',num2str(error)])
hold off