matlab ga优化的bp,lstm

一、GA优化BP

1.1 一列数据变x个输入y个输出的数据矩阵

  • 数据个数为n
  • 数据变成n-x-y+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];                       %交叉概率选择,01之间
pmutation=[0.1];                    %变异概率选择,01之间

%需要调整的参数
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;


猜你喜欢

转载自blog.csdn.net/qq_42306803/article/details/127468606