一、GA优化BP
1.1 一列数据变x个输入y个输出的数据矩阵
function [newData] = change(data,xlen,ylen)
%data是源数据
%xlen:输入的长度,ylen:输出的长度
[row col] = size(data);
cishu = row - xlen -ylen +1;
row1 = cishu;
col1 = xlen+ylen;
newData = zeros(row1,col1);
for i = 1:cishu
newData(i,:) = data(i:xlen+ylen+i-1,1);
end
1.2 普通bp,误差很大
- flag设置train和test比率
- src是一列数据
function [] = bp(src,xlen,ylen,flag)
%src是1列数据
%outFlag是以第几组数据为准
outFlag = 1;
data = change(src,xlen,ylen);
[row col] = size(data);
%% 此程序为matlab编程实现的BP神经网络
% 清空环境变量
% clear
% close all
% clc
%每一行是一个样本,列代表变量
%%第一步 读取数据
trainend = row*flag;
%% 第二步 设置训练数据和预测数据
input_train = data(1:trainend,1:xlen)';
output_train =data(1:trainend,xlen+1:col)';
input_test = data(trainend+1:row,1:xlen)';
output_test =data(trainend+1:row,xlen+1:col)';
%节点个数
inputnum=xlen; % 输入层节点数量
hiddennum=2*xlen+1;% 隐含层节点数量
outputnum=ylen; % 输出层节点数量
%% 第三本 训练样本数据归一化
[inputn,inputps]=mapminmax(input_train);%归一化到[-1,1]之间,inputps用来作下一次同样的归一化
[outputn,outputps]=mapminmax(output_train);
%% 第四步 构建BP神经网络
net=newff(inputn,outputn,hiddennum,{'tansig','purelin'},'trainlm');% 建立模型,传递函数使用purelin,采用梯度下降法训练
%init(net);
W1= net. iw{1, 1};%输入层到中间层的权值
% disp(W1)
B1 = net.b{1};%中间各层神经元阈值
% disp(B1)
W2 = net.lw{2,1};%中间层到输出层的权值
% disp(W2)
B2 = net. b{2};%输出层各神经元阈值
% disp(B2)
%% 第五步 网络参数配置( 训练次数,学习速率,训练目标最小误差等)
net.trainParam.epochs=1000; % 训练次数,这里设置为1000次
net.trainParam.lr=0.01; % 学习速率,这里设置为0.01
net.trainParam.goal=0.01; % 训练目标最小误差,这里设置为0.00001
%% 第六步 BP神经网络训练
net=train(net,inputn,outputn);%开始训练,其中inputn,outputn分别为输入输出样本
%% 第七步 测试样本归一化
inputn_test=mapminmax('apply',input_test,inputps);% 对样本数据进行归一化
%% 第八步 BP神经网络预测
an=sim(net,inputn_test); %用训练好的模型进行仿真
%% 第九步 预测结果反归一化与误差计算
test_simu=mapminmax('reverse',an,outputps); %把仿真得到的数据还原为原始的数量级
test_simu = test_simu';
test_simu = test_simu(:,ylen);
output_test = output_test';
output_test = output_test(:,ylen);
error=test_simu-output_test; %预测值和真实值的误差
% size(error)
%%第十步 真实值与预测值误差比较
plot(test_simu);
hold on
plot(output_test)
% figure('units','normalized','position',[0.119 0.2 0.38 0.5]);
% plot(output_test,'bo-');
% hold on;
% plot(test_simu,'r*-');
% hold on;
% plot(error,'square','MarkerFaceColor','b');
% legend('期望值','预测值','误差');
% xlabel('数据组数');
% ylabel('样本值');
% title('BP神经网络测试集的预测值与实际值对比图');
[c,l]=size(output_test);
MAE1=sum(abs(error))/l;
MSE1=error'*error/l;
RMSE1=MSE1^(1/2);
disp(['-----------------------误差计算--------------------------'])
disp(['隐含层节点数为',num2str(hiddennum),'时的误差结果如下:'])
disp(['平均绝对误差MAE为:',num2str(MAE1)])
disp(['均方误差MSE为: ',num2str(MSE1)])
disp(['均方根误差RMSE为: ',num2str(RMSE1)])
1.3 将一列数据变成需要的train和test
function [newData train test train_x train_y test_x test_y] = change(data,xlen,ylen,rate)
%data是源数据
%xlen:输入的长度,ylen:输出的长度
[row col] = size(data);
cishu = row - xlen -ylen +1;
row1 = cishu;
col1 = xlen+ylen;
newData = zeros(row1,col1);
for i = 1:cishu
newData(i,:) = data(i:xlen+ylen+i-1,1);
end
[row1 col1] = size(newData);
end1 = row1 * rate;
train = newData(1:end1,:);
test = newData(end1+1:row1,:);
train_x = newData(1:end1,1:xlen);
train_y = newData(1:end1,xlen+1:col1);
test_x = newData(end1+1:row1,1:xlen);
test_y = newData(end1+1:row1,xlen+1:col1);
1.4 mapminmax
- mapminmax按照行进行标准化,所以要保证行数一致
二、GA优化lstm
2.1 lstm
- 数据是读取的一列数据,依次取前5个数作为新的数据的一行,每行5个数
data = xlsread("./data.xlsx");
data = data(:,1);
rate = 0.8;
xlen = 5;
ylen = 1;
%多输入,一输出
%导入数据,数据必须是一维向量
[newData train test train_x train_y test_x test_y] = getTrainAndTest(data,xlen,ylen,rate);
data = newData;
[row col] = size(newData);
XTrain = newData(1:rate*row,1:xlen);
YTrain = newData(1:rate*row,xlen+1:col);
XTest = newData(rate*row+1:row,1:xlen);
YTest = newData(rate*row+1:row,xlen+1:col);
[mapXTrain,Xrule] = mapminmax(XTrain');
[mapYTrain,Yrule] = mapminmax(YTrain');
mapXTest = mapminmax('apply',XTest',Xrule);
mapYTest = mapminmax('apply',YTest',Yrule);
%将train,test数据标准化
numFeatures = xlen;
numResponses = ylen;
numHiddenUnits = 200;
%************************************
%---------------------------------------
layers = [ ...
sequenceInputLayer(numFeatures)
lstmLayer(numHiddenUnits)
fullyConnectedLayer(numResponses)
regressionLayer];
%接下来设置求解的各项参数,指定训练选项。将求解器设置为 'adam' 并进行 250 轮训练。要防止梯度爆炸,请将梯度阈值设置为 1。指定初始学习率 0.005,在 125 轮训练后通过乘以因子 0.2 来降低学习率。
options = trainingOptions('adam', ...
'MaxEpochs',200, ...
'GradientThreshold',1, ...
'InitialLearnRate',0.005, ...
'LearnRateSchedule','piecewise', ...
'LearnRateDropPeriod',400, ...
'LearnRateDropFactor',0.2, ...
'Verbose',0, ...
'Plots','training-progress');
%训练网络
net = trainNetwork(mapXTrain,mapYTrain,layers,options)
disp(net.Layers);
%初始网络状态
net = predictAndUpdateState(net,mapXTrain);
disp(net)
[row1 col1] = size(test_y);
YPred = zeros(ylen,row1);
for i = 1:row1
[net,YPred(:,i)] = predictAndUpdateState(net,mapXTest(:,i),'ExecutionEnvironment','cpu');
end
%Y预测值,反归一化
YPred = mapminmax('reverse',YPred,Yrule);
h1 = plot(YPred);
size(YPred);
hold on;
h2 = plot(test_y');
size(test_y);
test_y = test_y';
hold off;
legend([h1,h2],"预测值","原始数据");
error= YPred - test_y;
MAE = sum(abs(error)) / row1;
MSE = sum(error.^2) / row1;
RMSE = sqrt(MSE);
fprintf("MAE:%.6f\n",MAE );
fprintf("MSE:%.6f\n",MSE);
fprintf("RMSE:%.6f\n",RMSE);
2.2 GA-lstm
data = xlsread("./data.xlsx");
data = data(:,1);
rate = 0.8;
xlen = 5;
ylen = 1;
%多输入,一输出
%导入数据,数据必须是一维向量
[newData train test train_x train_y test_x test_y] = getTrainAndTest(data,xlen,ylen,rate);
data = newData;
[row col] = size(newData);
XTrain = newData(1:rate*row,1:xlen);
YTrain = newData(1:rate*row,xlen+1:col);
XTest = newData(rate*row+1:row,1:xlen);
YTest = newData(rate*row+1:row,xlen+1:col);
[mapXTrain,Xrule] = mapminmax(XTrain');
[mapYTrain,Yrule] = mapminmax(YTrain');
mapXTest = mapminmax('apply',XTest',Xrule);
mapYTest = mapminmax('apply',YTest',Yrule);
%将train,test数据标准化
%隐藏节点数
numHiddenUnits = 12;
MaxEpochs = 2;
InitialLearnRate = 0.005;
numFeatures = xlen;
numResponses = ylen;
%% 遗传算法参数初始化
maxgen=2; %进化代数,即迭代次数
sizepop=5; %种群规模
pcross=[0.3]; %交叉概率选择,0和1之间
pmutation=[0.1]; %变异概率选择,0和1之间
%需要调整的参数
numsum=3;
lenchrom=ones(1,numsum);
%网络阈值取值范围是-3~3
bound=[13 30; 10 30;0.001 0.01]; %数据范围
%fitness:适应度
%------------------------------------------------------种群初始化--------------------------------------------------------
individuals=struct('fitness',zeros(1,sizepop), 'chrom',[]); %将种群信息定义为一个结构体
avgfitness=[]; %每一代种群的平均适应度
bestfitness=[]; %每一代种群的最佳适应度
bestchrom=[]; %适应度最好的染色体
%初始化种群
for i=1:sizepop
%随机产生一个种群
individuals.chrom(i,:)=Code(lenchrom,bound); %编码(binary和grey的编码结果为一个实数,float的编码结果为一个实数向量)
x=individuals.chrom(i,:);
%计算适应度
individuals.fitness(i)=lstmfun(x,xlen,ylen,mapXTrain,mapYTrain,mapXTest,test_y,Yrule); %染色体的适应度
end
%找最好的染色体
[bestfitness, bestindex]=min(individuals.fitness);
bestchrom=individuals.chrom(bestindex,:); %最好的染色体
avgfitness=sum(individuals.fitness)/sizepop; %染色体的平均适应度
% 记录每一代进化中最好的适应度和平均适应度
trace=[avgfitness bestfitness];
%% 迭代求解最佳初始阀值和权值
% 进化开始
for i=1:maxgen
% 选择
individuals=Select(individuals,sizepop);
avgfitness=sum(individuals.fitness)/sizepop;
%交叉
individuals.chrom=Cross(pcross,lenchrom,individuals.chrom,sizepop,bound);
% 变异
individuals.chrom=Mutation(pmutation,lenchrom,individuals.chrom,sizepop,i,maxgen,bound);
% 计算适应度
for j=1:sizepop
x=individuals.chrom(j,:); %解码
individuals.fitness(j)=lstmfun(x,xlen,ylen,mapXTrain,mapYTrain,mapXTest,test_y,Yrule);
end
%找到最小和最大适应度的染色体及它们在种群中的位置
[newbestfitness,newbestindex]=min(individuals.fitness);
[worestfitness,worestindex]=max(individuals.fitness);
% 代替上一次进化中最好的染色体
if bestfitness>newbestfitness
bestfitness=newbestfitness;
bestchrom=individuals.chrom(newbestindex,:);
end
individuals.chrom(worestindex,:)=bestchrom;
individuals.fitness(worestindex)=bestfitness;
avgfitness=sum(individuals.fitness)/sizepop;
trace=[trace;avgfitness bestfitness]; %记录每一代进化中最好的适应度和平均适应度
end
%% 遗传算法结果分析
figure(1)
[r, c]=size(trace);
plot([1:r]',trace(:,1),'b--');%平均适应度曲线
hold on %继续绘图
plot([1:r]',trace(:,2),'r-'); %每一代种群的最佳适应度曲线
title(['适应度曲线 ' '终止代数=' num2str(maxgen)]);
xlabel('进化代数');ylabel('适应度');
legend('平均适应度','最佳适应度');
x=bestchrom;
%% 把最优初始阀值权值赋予网络预测
% %用遗传算法优化的BP网络进行值预测
numHiddenUnits = round(x(1));
MaxEpochs = round(x(1));
InitialLearnRate = x(3);
layers = [ ...
sequenceInputLayer(numFeatures)
lstmLayer(numHiddenUnits)
fullyConnectedLayer(numResponses)
regressionLayer];
%接下来设置求解的各项参数,指定训练选项。将求解器设置为 'adam' 并进行 250 轮训练。要防止梯度爆炸,请将梯度阈值设置为 1。指定初始学习率 0.005,在 125 轮训练后通过乘以因子 0.2 来降低学习率。
options = trainingOptions('adam', ...
'MaxEpochs',MaxEpochs, ...
'GradientThreshold',1, ...
'InitialLearnRate',InitialLearnRate, ...
'LearnRateSchedule','piecewise', ...
'LearnRateDropPeriod',400, ...
'LearnRateDropFactor',0.2, ...
'Verbose',0, ...
'Plots','training-progress');
%训练网络
net = trainNetwork(mapXTrain,mapYTrain,layers,options);
%初始网络状态
net = predictAndUpdateState(net,mapXTrain);
[row1 col1] = size(test_y);
YPred = zeros(ylen,row1);
for i = 1:row1
[net,YPred(:,i)] = predictAndUpdateState(net,mapXTest(:,i),'ExecutionEnvironment','cpu');
end
%Y预测值,反归一化
YPred = mapminmax('reverse',YPred,Yrule);
h1 = plot(YPred);
size(YPred);
hold on;
h2 = plot(test_y');
size(test_y);
test_y = test_y';
hold off;
legend([h1,h2],"预测值","原始数据");
error= YPred - test_y;
MAE = sum(abs(error)) / row1;
MSE = sum(error.^2) / row1;
RMSE = sqrt(MSE);
fprintf("MAE:%.6f\n",MAE );
fprintf("MSE:%.6f\n",MSE);
fprintf("RMSE:%.6f\n",RMSE);
fprintf("%d %d %.6f \n", numHiddenUnits,MaxEpochs,InitialLearnRate);
2.3 lstmfun
function [MAE] = lstmfun(x,xlen,ylen,mapXTrain,mapYTrain,mapXTest,test_y,Yrule)
numFeatures = xlen;
numResponses = ylen;
numHiddenUnits = round(x(1));
MaxEpochs = round(x(1));
InitialLearnRate = x(3);
%************************************
%---------------------------------------
layers = [ ...
sequenceInputLayer(numFeatures)
lstmLayer(numHiddenUnits)
fullyConnectedLayer(numResponses)
regressionLayer];
%接下来设置求解的各项参数,指定训练选项。将求解器设置为 'adam' 并进行 250 轮训练。要防止梯度爆炸,请将梯度阈值设置为 1。指定初始学习率 0.005,在 125 轮训练后通过乘以因子 0.2 来降低学习率。
options = trainingOptions('adam', ...
'MaxEpochs',MaxEpochs, ...
'GradientThreshold',1, ...
'InitialLearnRate',InitialLearnRate, ...
'LearnRateSchedule','piecewise', ...
'LearnRateDropPeriod',400, ...
'LearnRateDropFactor',0.2, ...
'Verbose',0, ...
'Plots','training-progress');
%训练网络
net = trainNetwork(mapXTrain,mapYTrain,layers,options);
%初始网络状态
net = predictAndUpdateState(net,mapXTrain);
[row1 col1] = size(test_y);
YPred = zeros(ylen,row1);
for i = 1:row1
[net,YPred(:,i)] = predictAndUpdateState(net,mapXTest(:,i),'ExecutionEnvironment','cpu');
end
%Y预测值,反归一化
YPred = mapminmax('reverse',YPred,Yrule);
test_y = test_y';
error= YPred - test_y;
MAE = sum(abs(error)) / row1;