目录
传统的BP神经网络训练采用的是误差反向传播学习算法,它的优化目标函数相对复杂,较容易出现陷人局部最优、收敛速度慢等问题[6]。由于BP神经网络的训练算法实质上是对其网络权值和阈值进行迭代调整,因此用蚁群优化算法替代BP算法完成对神经网络权阈值的迭代调整,并最终完成神经网络的训练。
蚁群算法解决优化问题的基本思路为:用蚂蚁的行走路径表示待优化问题的可行解,整个蚂蚁群体的所有路径构成待优化问题的解空间。路径较短的蚂蚁释放较多的信息素。经过一定时间,信息素浓度在较短的路径上累计较高,所有选择此路径的蚂蚁也逐渐增多,最终,整个蚁群会在正反馈的作用下集中在最佳路径上,此时对应的便是待优化问题的最优解。
首先根据权值和阈值的取值池间,将的E义以刘你以S个等长区间,即每个区间的长度被作s等分,将区间的临界值或选择区间中的随机值作为候选值。确定参数个数n,包括网络中所有的权阈值。每个参数Pi(i=1,2,…,n)对应个有S个元素的集合l, ,这些元素为Pi的可能取值。
1)参数初始化:将所有权值和阈值进行S等分,所有区间初始信息素О,信息素残留系教入,1后尽系代i,前区间信息表为Tabu,最大迭代次数C,网络全局误差E,最大学习次数N;
2)权值和阈值选择:蚁群m只蚂蚁,对于蚂蚁k依据概率公式(2)的寻路规则进行选择节点所在区间,蚁群迭代一次则完成一次解的构造:
式中为集合中第j个元素的信息素值;
3)蚁群寻优判断:蚁群迭代一次得到的构造解,则是当前迭代后得到误差最小的一组解,计算误差Ec ,判断是否达到蚁群要求,若是则转到4),否则转到5);
4)网络训练:将蚁群迭代得到的最优构造解,作为初始权值和阈值,选取数据集对网络进行训练,直到满足结束条件即最大学习次数,完成学习。否则,继续学习;
5)更新信息素:根据式(3)、式( 4)、式(5)对所有区间信息素全局更新,并重置信息表:
6)蚁群遍历:重复步骤2)到步骤3)。其算法如图1所示。
图1 ACO-BP算法流程图
主函数
- %% 清空环境变量
- clc
- clear
- close all
- format compact
- %% 网络结构建立
- %% 清空环境变量
- clc
- clear
- close all
- format compact
- %% 网络结构建立
- %读取数据
- data=xlsread('天气_电量_数据.xlsx','C12:J70');%前7列为每个时刻的发电量 最后列为天气
-
- for i=1:58
- input(i,:)=[data(i,:) data(i+1,end)];
- output(i,:)=data(i+1,1:7);
- end
-
- %% 节点个数
- inputnum=9;%输入 前一天7个时刻的电量+前一天的天气+预测日的天气
- hiddennum=5;
- outputnum=7;%预测日7个时刻的发电量
-
- %% 训练数据和预测数据 最后一天用来测试 前面的都拿来训练
- input_train=input(1:57,:)';
- input_test=input(58,:)';
- output_train=output(1:57,:)';
- output_test=output(58,:)';
-
- %选连样本输入输出数据归一化
- [inputn,inputps]=mapminmax(input_train);
- [outputn,outputps]=mapminmax(output_train);
- inputn_test=mapminmax('apply',input_test,inputps);
- %%
- %构建网络
- net=newff(inputn,outputn,hiddennum);
- %寻优
- [bestnest,trace]=antforelm(inputnum,hiddennum,outputnum,net,inputn,outputn);
- figure
- plot(trace)
- title('适应度曲线')
- xlabel('迭代数')
- ylabel('适应度值')
-
-
- %% 把最优初始阀值权值赋予网络预测
- x=bestnest;
- % 用CS优化的BP网络进行值预测
- w1=x(1:inputnum*hiddennum);
- B1=x(inputnum*hiddennum+1:inputnum*hiddennum+hiddennum);
- w2=x(inputnum*hiddennum+hiddennum+1:inputnum*hiddennum+hiddennum+hiddennum*outputnum);
- B2=x(inputnum*hiddennum+hiddennum+hiddennum*outputnum+1:inputnum*hiddennum+hiddennum+hiddennum*outputnum+outputnum);
-
- net.iw{1,1}=reshape(w1,hiddennum,inputnum);
- net.lw{2,1}=reshape(w2,outputnum,hiddennum);
- net.b{1}=reshape(B1,hiddennum,1);
- net.b{2}=B2';
- %% BP网络训练
- %网络进化参数
- net.trainParam.epochs=200;
- net.trainParam.lr=0.1;
- %net.trainParam.goal=0.00001;
- %网络训练
- [net,per2]=train(net,inputn,outputn);
- %% BP网络预测
- %数据归一化
- inputn_test=mapminmax('apply',input_test,inputps);
- an=sim(net,inputn_test);
- test_simu=mapminmax('reverse',an,outputps);
- error=test_simu-output_test;
- %%
- figure
- a1=output_test;
- a2=test_simu;
- plot(a1,'*-');hold on
- plot(a2,'O-')
- title('各时刻发电量实际值与预测值')
- xlabel('')
- legend('原始数据','bp预测数据')
- set(gca,'XTick',1:7,...
- 'XTickLabel',{'9:00','10:00','11:00','12:00','13:00','14:00','15:00'},...
- 'TickLength',[0 0]);
- grid on
- ylabel('发电量(KW)')
- %% You can replace the following by your own functions
-
- function error = fun(x,inputnum,hiddennum,outputnum,net,inputn,outputn)
- %该函数用来计算适应度值
- %x input 个体
- %inputnum input 输入层节点数
- %outputnum input 隐含层节点数
- %net input 网络
- %inputn input 训练输入数据
- %outputn input 训练输出数据
- %error output 个体适应度值
-
- %提取
- w1=x(1:inputnum*hiddennum);
- B1=x(inputnum*hiddennum+1:inputnum*hiddennum+hiddennum);
- w2=x(inputnum*hiddennum+hiddennum+1:inputnum*hiddennum+hiddennum+hiddennum*outputnum);
- B2=x(inputnum*hiddennum+hiddennum+hiddennum*outputnum+1:inputnum*hiddennum+hiddennum+hiddennum*outputnum+outputnum);
-
-
- %网络进化参数
- net.trainParam.epochs=20;
- net.trainParam.lr=0.1;
- net.trainParam.goal=0.00001;
- net.trainParam.show=100;
- net.trainParam.showWindow=0;
-
- %网络权值赋值
- net.iw{1,1}=reshape(w1,hiddennum,inputnum);
- net.lw{2,1}=reshape(w2,outputnum,hiddennum);
- net.b{1}=reshape(B1,hiddennum,1);
- net.b{2}=B2';
- % %网络训练
- % net=train(net,inputn,outputn);
- an=sim(net,inputn);
- % an-outputn
- error0=sum(abs(an-outputn));
- error=sum(error0);%以均方差作为适应度函数
- %% Replace some nests by constructing new solutions/nests
- function new_nest=empty_nests(nest,Lb,Ub,pa)
- % A fraction of worse nests are discovered with a probability pa
- n=size(nest,1);
- % Discovered or not -- a status vector
- K=rand(size(nest))>pa;
-
- % In the real world, if a cuckoo's egg is very similar to a host's eggs, then
- % this cuckoo's egg is less likely to be discovered, thus the fitness should
- % be related to the difference in solutions. Therefore, it is a good idea
- % to do a random walk in a biased way with some random step sizes.
- %% New solution by biased/selective random walks
- stepsize=rand*(nest(randperm(n),:)-nest(randperm(n),:));
- new_nest=nest+stepsize.*K;
- for j=1:size(new_nest,1)
- s=new_nest(j,:);
- new_nest(j,:)=simplebounds(s,Lb,Ub);
- end
- function [y,trace]=antforelm(inputnum,hiddennum,outputnum,net,inputn_train,label_train);%蚁群算法%%%%%%%%%%%%%%%%%%%%蚁群算法求函数极值%%%%%%%%%%%%%%%%%%%%%%%
- %%%%%%%%%%%%%%%%%%%%%%%%%初始化%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- m=5; %蚂蚁个数
- G_max=100; %最大迭代次数
- Rho=0.5; %信息素蒸发系数
- P0=0.5; %转移概率常数
- XMAX= 1; %搜索变量x最大值
- XMIN=-1; %搜索变量x最小值
- d=inputnum*hiddennum+hiddennum+hiddennum*outputnum+outputnum;
- %%%%%%%%%%%%%%%%%随机设置蚂蚁初始位置%%%%%%%%%%%%%%%%%%%%%%
- for i=1:m
- X(i,:)=(XMIN+(XMAX-XMIN).*rand(1,d));
- Tau(i)=fun(X(i,:),inputnum,hiddennum,outputnum,net,inputn_train,label_train);
- end
-
- bestfitness=inf;
- bestfitness_position=inf*ones(1,d);
-
- step=0.1; %局部搜索步长
- for NC=1:G_max
- NC
- lamda=1/NC;
- [Tau_best,BestIndex]=min(Tau);
- %%%%%%%%%%%%%%%%%%计算状态转移概率%%%%%%%%%%%%%%%%%%%%
- for i=1:m
- P(NC,i)=(Tau(BestIndex)-Tau(i))/Tau(BestIndex);
- end
- %%%%%%%%%%%%%%%%%%%%%%位置更新%%%%%%%%%%%%%%%%%%%%%%%%
- for i=1:m
- fun_i=fun(X(i,:),inputnum,hiddennum,outputnum,net,inputn_train,label_train);
- %%%%%%%%%%%%%%%%%局部搜索%%%%%%%%%%%%%%%%%%%%%%
- if P(NC,i)<P0
- temp1=X(i,:)+(rand(1,d))*step*lamda;
-
- else
- %%%%%%%%%%%%%%%%全局搜索%%%%%%%%%%%%%%%%%%%%%%%
- temp1=X(i,:)+(XMAX-XMIN)*(rand(1,d));
- end
- %%%%%%%%%%%%%%%%%%%%%边界处理%%%%%%%%%%%%%%%%%%%%%%%
- for j=1:d
- if temp1(j)<XMIN
- temp1(j)=rand;
- end
- if temp1(j)>XMAX
- temp1(j)=rand;
- end
- end
- fun_temp=fun(temp1,inputnum,hiddennum,outputnum,net,inputn_train,label_train);
- %%%%%%%%%%%%%%%%%%蚂蚁判断是否移动%%%%%%%%%%%%%%%%%%
- if fun_temp
- X(i,:)=temp1;
- Tau(i)=fun_temp;
- end
- end
- %%%%%%%%%%%%%%%%%%%%%%%更新信息素%%%%%%%%%%%%%%%%%%%%%%%
- for i=1:m
- Tau(i)=(1-Rho)*Tau(i)+Tau(i);
- end
- [value,index]=min(Tau);
- %%
- if value
- bestfitness=value;
- bestfitness_position=X(index,:);
- end
- trace(NC)=bestfitness;
-
- end
- y=bestfitness_position; %最优变量
-
5 运行结果
6 参考文献
[1]陈智雨,陆金桂.基于ACO-BP神经网络的光伏系统发电功率预测[J].机械制造与自动化,2020,49(01):173-175+187.DOI:10.19344/j.cnki.issn1671-5276.2020.01.047.
7 写在最后
部分理论引用网络文献,如有侵权请联系删除。
%% 清空环境变量
clc
clear
close all
format compact
%% 网络结构建立
%% 清空环境变量
clc
clear
close all
format compact
%% 网络结构建立
%读取数据
data=xlsread('天气_电量_数据.xlsx','C12:J70');%前7列为每个时刻的发电量 最后列为天气
for i=1:58
input(i,:)=[data(i,:) data(i+1,end)];
output(i,:)=data(i+1,1:7);
end
%% 节点个数
inputnum=9;%输入 前一天7个时刻的电量+前一天的天气+预测日的天气
hiddennum=5;
outputnum=7;%预测日7个时刻的发电量
%% 训练数据和预测数据 最后一天用来测试 前面的都拿来训练
input_train=input(1:57,:)';
input_test=input(58,:)';
output_train=output(1:57,:)';
output_test=output(58,:)';
%选连样本输入输出数据归一化
[inputn,inputps]=mapminmax(input_train);
[outputn,outputps]=mapminmax(output_train);
inputn_test=mapminmax('apply',input_test,inputps);
%%
%构建网络
net=newff(inputn,outputn,hiddennum);
%寻优
[bestnest,trace]=antforelm(inputnum,hiddennum,outputnum,net,inputn,outputn);
figure
plot(trace)
title('适应度曲线')
xlabel('迭代数')
ylabel('适应度值')
%% 把最优初始阀值权值赋予网络预测
x=bestnest;
% 用CS优化的BP网络进行值预测
w1=x(1:inputnum*hiddennum);
B1=x(inputnum*hiddennum+1:inputnum*hiddennum+hiddennum);
w2=x(inputnum*hiddennum+hiddennum+1:inputnum*hiddennum+hiddennum+hiddennum*outputnum);
B2=x(inputnum*hiddennum+hiddennum+hiddennum*outputnum+1:inputnum*hiddennum+hiddennum+hiddennum*outputnum+outputnum);
net.iw{1,1}=reshape(w1,hiddennum,inputnum);
net.lw{2,1}=reshape(w2,outputnum,hiddennum);
net.b{1}=reshape(B1,hiddennum,1);
net.b{2}=B2';
%% BP网络训练
%网络进化参数
net.trainParam.epochs=200;
net.trainParam.lr=0.1;
%net.trainParam.goal=0.00001;
%网络训练
[net,per2]=train(net,inputn,outputn);
%% BP网络预测
%数据归一化
inputn_test=mapminmax('apply',input_test,inputps);
an=sim(net,inputn_test);
test_simu=mapminmax('reverse',an,outputps);
error=test_simu-output_test;
%%
figure
a1=output_test;
a2=test_simu;
plot(a1,'*-');hold on
plot(a2,'O-')
title('各时刻发电量实际值与预测值')
xlabel('')
legend('原始数据','bp预测数据')
set(gca,'XTick',1:7,...
'XTickLabel',{'9:00','10:00','11:00','12:00','13:00','14:00','15:00'},...
'TickLength',[0 0]);
grid on
ylabel('发电量(KW)')