%% 初始化
clear
close all
clc
warning off
%% 数据读取
data=xlsread('数据.xlsx','Sheet1','A1:N252'); %%使用xlsread函数读取EXCEL中对应范围的数据即可
%输入输出数据
input=data(:,1:end-1); %data的第一列-倒数第二列为特征指标
output=data(:,end); %data的最后面一列为输出的指标值
N=length(output); %全部样本数目
testNum=15; %设定测试样本数目
trainNum=N-testNum; %计算训练样本数目
%% 划分训练集、测试集
input_train = input(1:trainNum,:)';
output_train =output(1:trainNum)';
input_test =input(trainNum+1:trainNum+testNum,:)';
output_test =output(trainNum+1:trainNum+testNum)';
%% 数据归一化
[inputn,inputps]=mapminmax(input_train,0,1);
[outputn,outputps]=mapminmax(output_train);
inputn_test=mapminmax('apply',input_test,inputps);
%% 获取输入层节点、输出层节点个数
inputnum=size(input,2);
outputnum=size(output,2);
disp('/////////////////////////////////')
disp('神经网络结构...')
disp(['输入层的节点数为:',num2str(inputnum)])
disp(['输出层的节点数为:',num2str(outputnum)])
disp(' ')
disp('隐含层节点的确定过程...')
%确定隐含层节点个数
%采用经验公式hiddennum=sqrt(m+n)+a,m为输入层节点个数,n为输出层节点个数,a一般取为1-10之间的整数
MSE=1e+5; %初始化最小误差
for hiddennum=fix(sqrt(inputnum+outputnum))+1:fix(sqrt(inputnum+outputnum))+10
%构建网络
net=newff(inputn,outputn,hiddennum);
% 网络参数
net.trainParam.epochs=1000; % 训练次数
net.trainParam.lr=0.01; % 学习速率
net.trainParam.goal=0.000001; % 训练目标最小误差
% 网络训练
net=train(net,inputn,outputn);
an0=sim(net,inputn); %仿真结果
mse0=mse(outputn,an0); %仿真的均方误差
disp(['隐含层节点数为',num2str(hiddennum),'时,训练集的均方误差为:',num2str(mse0)])
%更新最佳的隐含层节点
if mse0<MSE
MSE=mse0;
hiddennum_best=hiddennum;
end
end
disp(['最佳的隐含层节点数为:',num2str(hiddennum_best),',相应的均方误差为:',num2str(MSE)])
%% 构建最佳隐含层节点的BP神经网络
disp(' ')
disp('标准的BP神经网络:')
net0=newff(inputn,outputn,hiddennum_best,{'tansig','purelin'},'trainlm');% 建立模型
%网络参数配置
net0.trainParam.epochs=1000; % 训练次数,这里设置为1000次
net0.trainParam.lr=0.01; % 学习速率,这里设置为0.01
net0.trainParam.goal=0.00001; % 训练目标最小误差,这里设置为0.0001
net0.trainParam.show=25; % 显示频率,这里设置为每训练25次显示一次
net0.trainParam.mc=0.01; % 动量因子
net0.trainParam.min_grad=1e-6; % 最小性能梯度
net0.trainParam.max_fail=6; % 最高失败次数
%开始训练
net0=train(net0,inputn,outputn);
%预测
an0=sim(net0,inputn_test); %用训练好的模型进行仿真
%预测结果反归一化与误差计算
test_simu0=mapminmax('reverse',an0,outputps); %把仿真得到的数据还原为原始的数量级
%误差指标
[mae0,mse0,rmse0,mape0,error0,errorPercent0]=calc_error(output_test,test_simu0);
%% 原子搜索算法寻最优权值阈值
disp(' ')
disp('Tent-ASO优化BP神经网络:')
net=newff(inputn,outputn,hiddennum_best,{'tansig','purelin'},'trainlm');% 建立模型
%网络参数配置
net.trainParam.epochs=1000; % 训练次数,这里设置为1000次
net.trainParam.lr=0.01; % 学习速率,这里设置为0.01
net.trainParam.goal=0.00001; % 训练目标最小误差,这里设置为0.0001
net.trainParam.show=25; % 显示频率,这里设置为每训练25次显示一次
net.trainParam.mc=0.01; % 动量因子
net.trainParam.min_grad=1e-6; % 最小性能梯度
net.trainParam.max_fail=6; % 最高失败次数
%初始化Tent-ASO参数
popsize=30; %初始种群规模
maxgen=50; %最大进化代数
dim=inputnum*hiddennum_best+hiddennum_best+hiddennum_best*outputnum+outputnum; %自变量个数
lb=repmat(-3,1,dim); %自变量下限
ub=repmat(3,1,dim); %自变量上限
alpha=50; %深度权重
beta=0.2; %乘数权重
% Tent混沌映射初始化原子的种群位置
k=3; %k为1到n的正整数,Tent映射初始化k*popsize个种群,从中选出适应度最好的popsize个个体作为初始种群
Atom_Pop= tentInitialization(popsize*k,dim,ub,lb);
% 计算初始的原子适应度
Fitness=zeros(popsize*k,1);
for i=1:popsize*k
Fitness(i)=fitness(Atom_Pop(i,:),inputnum,hiddennum_best,outputnum,net,inputn,outputn,output_train,inputn_test,outputps,output_test);
end
% 排序,得到适应度最好的popsize个个体作为初始种群
[Fitness, index]= sort(Fitness);%排序
Fitness=Fitness(1:popsize);%选出初始的popsize个最佳个体
index=index(1:popsize);
Atom_Pop=Atom_Pop(index,:);
% 初始化原子的速度
Atom_V=zeros(popsize,dim);
for i=1:dim
Atom_V(:,i)=rand(popsize,1).*(ub(i)-lb(i))+lb(i);
end
%计算初始的最优位置与适应度
[~,Index]=min(Fitness);
Fit_XBest=Fitness(Index);
X_Best=Atom_Pop(Index,:);
%存储进化信息的矩阵
Convergence_curve=zeros(maxgen,1);
%% 开始循环
h=waitbar(0,'Tent-ASO optimization...');
for Iteration=1:maxgen
%更新原子加速度
Atom_Acc=Acceleration(Atom_Pop,Fitness,Iteration,maxgen,dim,popsize,X_Best,alpha,beta);
%更新原子速度
Atom_V=rand(popsize,dim).*Atom_V+Atom_Acc;
%更新原子位置
Atom_Pop=Atom_Pop+Atom_V;
%计算原子的适应度
for i=1:popsize
% 位置越界调整
TU= Atom_Pop(i,:)>ub;
TL= Atom_Pop(i,:)<lb;
Atom_Pop(i,:)=(Atom_Pop(i,:).*(~(TU+TL)))+((rand(1,dim).*(ub-lb)+lb).*(TU+TL));
Fitness(i)=fitness(Atom_Pop(i,:),inputnum,hiddennum_best,outputnum,net,inputn,outputn,output_train,inputn_test,outputps,output_test);
end
%更新最优适应度
[Max_Fitness,Index]=min(Fitness); %误差越小,模型精度越高,所以升序排列
if Max_Fitness<Fit_XBest
Fit_XBest=Max_Fitness;
X_Best=Atom_Pop(Index,:);
else
r=fix(rand*popsize)+1;
Atom_Pop(r,:)=X_Best;
end
Convergence_curve(Iteration)=Fit_XBest;
waitbar( Iteration/maxgen,h)
end
close(h)
setdemorandstream(pi);
%% 绘制进化曲线
figure
plot(Convergence_curve,'r-','linewidth',2)
xlabel('进化代数')
ylabel('均方误差')
legend('最佳适应度')
title('Tent-ASO的进化收敛曲线')
w1=X_Best(1:inputnum*hiddennum_best); %输入层到中间层的权值
B1=X_Best(inputnum*hiddennum_best+1:inputnum*hiddennum_best+hiddennum_best); %中间各层神经元阈值
w2=X_Best(inputnum*hiddennum_best+hiddennum_best+1:inputnum*hiddennum_best+hiddennum_best+hiddennum_best*outputnum); %中间层到输出层的权值
B2=X_Best(inputnum*hiddennum_best+hiddennum_best+hiddennum_best*outputnum+1:inputnum*hiddennum_best+hiddennum_best+hiddennum_best*outputnum+outputnum); %输出层各神经元阈值
%矩阵重构
net.iw{1,1}=reshape(w1,hiddennum_best,inputnum);
net.lw{2,1}=reshape(w2,outputnum,hiddennum_best);
net.b{1}=reshape(B1,hiddennum_best,1);
net.b{2}=reshape(B2,outputnum,1);
%% 优化后的神经网络训练
net=train(net,inputn,outputn);%开始训练,其中inputn,outputn分别为输入输出样本
%% 优化后的神经网络测试
an1=sim(net,inputn_test);
test_simu1=mapminmax('reverse',an1,outputps); %把仿真得到的数据还原为原始的数量级
%误差指标
[mae1,mse1,rmse1,mape1,error1,errorPercent1]=calc_error(output_test,test_simu1);
%% 作图
figure
plot(output_test,'b-*','linewidth',1)
hold on
plot(test_simu0,'r-v','linewidth',1,'markerfacecolor','r')
hold on
plot(test_simu1,'k-o','linewidth',1,'markerfacecolor','k')
legend('真实值','BP预测值','Tent-ASO BP预测值')
xlabel('测试样本编号')
ylabel('指标值')
title('Tent-ASO优化前后的BP神经网络预测值和真实值对比图')
figure
plot(error0,'rv-','markerfacecolor','r')
hold on
plot(error1,'ko-','markerfacecolor','k')
legend('BP预测误差','Tent-ASO BP预测误差')
xlabel('测试样本编号')
ylabel('预测偏差')
title('Tent-ASO优化前后的BP神经网络预测值和真实值误差对比图')
disp(' ')
disp('/////////////////////////////////')
disp('打印结果表格')
disp('样本序号 实测值 BP预测值 Tent-ASO-BP值 BP误差 Tent-ASO-BP误差')
for i=1:testNum
disp([i output_test(i),test_simu0(i),test_simu1(i),error0(i),error1(i)])
end
% 以下命令删除后便不会显示交流群信息
load data1.mat
figure('MenuBar','none')
imshow(b)
text(0.