LSTM的使用场景
1、基于LSTM的数据回归预测
数据回归预测一般应用在不考虑时间的场景中,只是简单的将拥有的数据分为输入及输出两类,之后将输入与输出划分为测试集与训练集,用训练集去训练模型,测试集检验模型性能,简单例子如下:
% 导入数据
res = readmatrix("数据.xlsx");
%% 划分训练集和测试集
temp = randperm(80);%数据回归预测中不考虑时间,故可将测试数据进行乱序
P_train = res(temp(1:60),1:7)';
T_train = res(temp(1:60),8)';
M = size(P_train,2);%size(A,1)返回A矩阵列数,size(A,2)返回A矩阵行数
P_test = res(temp(61:end),1:7)';
T_test = res(temp(61:end),8)';
N = size(P_test,2);
%% 数据归一化
[P_train,ps_input] = mapminmax(P_train,0,1);
P_test = mapminmax('apply',P_test,ps_input);
[t_train,ps_output] = mapminmax(T_train,0,1);
t_test = mapminmax('apply',T_test,ps_output);
%% 数据平铺
P_train = double(reshape(P_train,7,1,1,M));
P_test = double(reshape(P_test,7,1,1,N));
t_train = t_train';
t_test = t_test';
%% 数据格式转换
for i = 1:M
p_train{i,1} = P_train(:,:,1,i);
end
for i = 1:N
p_test{i,1} = P_test(:,:,1,i);
end
%% 创建模型
layers = [
sequenceInputLayer(7)%建立输入层
lstmLayer(4,'OutputMode','last')%LSTM层
reluLayer %relu激活层
fullyConnectedLayer(1)
regressionLayer];
%% 参数设置
options = trainingOptions('adam', ...
'MiniBatchSize', 30, ...
'MaxEpochs', 1200, ...
'InitialLearnRate', 1e-2, ...
'LearnRateSchedule', 'piecewise', ...
'LearnRateDropFactor', 0.5, ...
'LearnRateDropPeriod', 800, ...
'Plots','training-progress',...
'Verbose',false);
%% 训练模型
net = trainNetwork(p_train,t_train,layers,options);
%% 仿真预测
t_sim1 = predict(net,p_train);
t_sim2 = predict(net,p_test);
%% 数据反归一化
T_sim1 = mapminmax('reverse',t_sim1,ps_output);
T_sim2 = mapminmax('reverse',t_sim2,ps_output);
%% 均方根误差
error1 = sqrt(sum((T_sim1'-T_train).^2)./M);
error2 = sqrt(sum((T_sim2'-T_test).^2)./N);
%% 查看网络结构
analyzeNetwork(net)
%% 绘图
T = [T_train,T_test];
S = [T_sim1',T_sim2'];
figure
plot(1:80,T,1:80,S,'LineWidth',1);
legend('真实值','预测值')
xlabel('Time')
ylabel('Value')
title('5mm2550热电偶基于LSTM模型的数据预测')
grid
2、基于LSTM的数据分类预测
主要用于对一组数据的类别进行预测。此类情况与数据回归预测的区别在于此类情况的输出是固定的类别名或类别值,而不是一个存粹的数值。注意,在数据归一化时需要用到categorical函数,简单例子如下。
% 导入数据
res = readmatrix("数据.xlsx");
%% 划分训练集和测试集
temp = randperm(357);%数据回归预测中不考虑时间,故可将测试数据进行乱序
P_train = res(temp(1:240),1:12)';
T_train = res(temp(1:240),13)';
M = size(P_train,2);%size(A,1)返回A矩阵列数,size(A,2)返回A矩阵行数
P_test = res(temp(241:end),1:12)';
T_test = res(temp(241:end),13)';
N = size(P_test,2);
%% 数据归一化
[P_train,ps_input] = mapminmax(P_train,0,1);
P_test = mapminmax('apply',P_test,ps_input);
t_train = categorical(T_train)';
t_test = categorical(T_test)';
%% 数据平铺
P_train = double(reshape(P_train,12,1,1,M));
P_test = double(reshape(P_test,12,1,1,N));
t_train = t_train';
t_test = t_test';
%% 数据格式转换
for i = 1:M
p_train{i,1} = P_train(:,:,1,i);
end
for i = 1:N
p_test{i,1} = P_test(:,:,1,i);
end
%% 创建模型
layers = [
sequenceInputLayer(12) %建立输入层
lstmLayer(6,'OutputMode','last') %LSTM层
reluLayer %relu激活层
fullyConnectedLayer(4) %全连接层
softmaxLayer %分类层
classificationLayer];
%% 参数设置
options = trainingOptions('adam', ... %adam梯度下降算法
'MiniBatchSize', 100, ... %批大小
'MaxEpochs', 1000, ... %最大迭代次数
'InitialLearnRate', 1e-2, ... %初始学习率
'LearnRateSchedule', 'piecewise', ... %学习率下降
'LearnRateDropFactor', 0.1, ... %学习率下降因子
'LearnRateDropPeriod', 700, ... %经过700次训练后,学习率为0.01*0.1
'Shuffle','every-epoch',... %每次训练打乱数据集
'ValidationPatience',Inf,... %关闭验证
'Plots','training-progress',... %画出曲线
'Verbose',false);
%% 训练模型
net = trainNetwork(p_train,t_train,layers,options);
%% 仿真预测
t_sim1 = predict(net,p_train);
t_sim2 = predict(net,p_test);
%% 数据反归一化
T_sim1 = vec2ind(t_sim1);
T_sim2 = vec2ind(t_sim2);
%% 性能
error1 = sum((T_sim1 == T_train)) / M * 100;
error2 = sum((T_sim2 == T_test)) / N *100;
%% 查看网络结构
analyzeNetwork(net)
%% 数据排序
[T_train,index_1] = sort(T_train);
[T_test,index_2] = sort(T_test);
T_sim1 = T_sim1(index_1);
T_sim2 = T_sim2(index_2);
%% 绘图
figure
plot(1:M,T_train,'r-*',1:M,T_sim1,'b-o','LineWidth',1);
legend('真实值','预测值')
xlabel('预测样本')
ylabel('预测结果')
string = {'测试集预测集结果对比';['准确率=' num2str(error2) '%']};
title(string)
xlim([1,N])
grid
%% 混淆矩阵
figure
cm = confusionchart(T_train,T_sim1);
cm.Title = 'Confusion Matrix for Train Data';
cm.ColumnSummary = 'column-normalized';
cm.RowSummary = 'row-normalized';
figure
cm = confusionchart(T_test,T_sim2);
cm.Title = 'Confusion Matrix for Test Data';
cm.ColumnSummary = 'column-normalized';
cm.RowSummary = 'row-normalized';
3、 基于LSTM的时间序列预测
一般用于对与时间有关的数据序列进行预测,例如股票预测,温度预测等。方式:可将时间序列预测转换成数据回归预测,例如,将时间序列预测转换成通过前15个数据预测第16个数据,通过第2-16个数据预测第17个数据,以此类推。简单例子如下。
data = readmatrix("数据.xlsx");
%%
% 数据分析
num_samples = length(data);
kim = 15;
zim = 1;
% 划分数据集
for i = 1:num_samples-kim-zim+1
res(i,:) = [reshape(data(i:i+kim-1),1,kim),data(i+kim+zim-1)];
end
% 划分训练集和测试集
temp = 1:1:5485;
P_train = res(temp(1:4400),1:15)';
T_train = res(temp(1:4400),16)';
M = size(P_train,2);
P_test = res(temp(4401:end),1:15)';
T_test = res(temp(4401:end),16)';
N = size(P_test,2);
%数据归一化
[P_train,ps_input] = mapminmax(P_train,0,1);
P_test = mapminmax('apply',P_test,ps_input);
[t_train,ps_output] = mapminmax(T_train,0,1);
t_test = mapminmax('apply',T_test,ps_output);
% 数据平铺
P_train = double(reshape(P_train,15,1,1,M));
P_test = double(reshape(P_test,15,1,1,N));
t_train = t_train';
t_test = t_test';
% 数据格式转换
for i = 1:M
p_train{i,1} = P_train(:,:,1,i);
end
for i = 1:N
p_test{i,1} = P_test(:,:,1,i);
end
% 创建模型
layers = [
sequenceInputLayer(15)
lstmLayer(10,'OutputMode','last')
reluLayer
fullyConnectedLayer(1)
regressionLayer];
% 参数设置
options = trainingOptions('adam', ...
'MiniBatchSize', 2000, ...
'MaxEpochs', 800, ...
'InitialLearnRate', 1e-2, ...
'LearnRateSchedule', 'piecewise', ...
'LearnRateDropFactor', 0.5, ...
'LearnRateDropPeriod', 800, ...
'Plots','training-progress',...
'Verbose',false);
% 训练模型
net = trainNetwork(p_train,t_train,layers,options);
% 仿真预测
t_sim1 = predict(net,p_train);
t_sim2 = predict(net,p_test);
% 数据反归一化
T_sim1 = mapminmax('reverse',t_sim1,ps_output);
T_sim2 = mapminmax('reverse',t_sim2,ps_output);
% 均方根误差
error1 = sqrt(sum((T_sim1'-T_train).^2)./M);
error2 = sqrt(sum((T_sim2'-T_test).^2)./N);
% 查看网络结构
analyzeNetwork(net)
% 绘图
T = [T_train,T_test];
S = [T_sim1',T_sim2'];
figure
plot(1:5485,T,1:5485,S,'LineWidth',1);
legend('真实值','预测值')
xlabel('Time')
ylabel('Value')
title('4mm1525红外基于LSTM模型的数据预测')
text(200,170,"error1:"+error1)
text(200,163,"error2:"+error2)
grid
% 4mm1525
Ppid = zeros(1,5500);
for t=1:1:1000
Ppid(t)=15;
end
for t=1000:1:2000
Ppid(t)=25;
end
for t=2000:1:3000
Ppid(t)=15;
end
for t=3000:1:4000
Ppid(t)=25;
end
for t=4000:1:5500
Ppid(t)=15;
end
Ppid = Ppid';
%% 热电偶单个预测
xlsx = readmatrix("../数据/4mm1525热电偶.xlsx");
data = zeros(1,5500);
data(1) = xlsx(1);
a = (xlsx(2)-xlsx(1))/99;
i=2;
for t=2:1:5500
if mod(t,99)==0
i = i+1;
a = (xlsx(i)-xlsx(i-1))/99;
end
data(t) = data(t-1)+a;
end
% 红外单个预测
data = readmatrix("../数据/4mm1525红外.xlsx");
data = data';
%% 数据拆分
numTimeStepsTrain = floor(0.8*numel(data));
dataTrain = data(1:numTimeStepsTrain+1);
dataTest = data(numTimeStepsTrain+1:end);
%% 数据归一化
mu = mean(dataTrain);
sig = std(dataTrain);
dataTrainStandardized = (dataTrain - mu) / sig;
XTrain = dataTrainStandardized(1:end-1);
YTrain = dataTrainStandardized(2:end);
%% 定义网络结构
layers = [
sequenceInputLayer(1,"Name","input")
lstmLayer(128,"Name","lstm")
dropoutLayer(0.2,"Name","drop")
fullyConnectedLayer(1,"Name","fc")
regressionLayer];
%% 定义训练参数
options = trainingOptions('adam',...
'MaxEpochs',150,...
'GradientThreshold',1,...
'InitialLearnRate',0.005,...
'LearnRateSchedule','piecewise',...
'LearnRateDropPeriod',125,...
'LearnRateDropFactor',0.2,...
'Verbose',0,...
'Plots','training-progress')
%% 训练网络
net = trainNetwork(XTrain,YTrain,layers,options);
%% 测试集归一化
dataTestStandardized = (dataTest - mu) / sig;
XTest = dataTestStandardized(1:end-1);
%% 预测
net = predictAndUpdateState(net,XTrain);
[net,YPred] = predictAndUpdateState(net,YTrain(end));
numTimeStepsTest = numel(XTest);
for i = 2:numTimeStepsTest
[net,YPred(:,i)] = predictAndUpdateState(net,YPred(:,i-1),'ExecutionEnvironment','cpu');
end
%% 反归一化
YPred = sig * YPred + mu;
%% 绘图
figure
plot(dataTrain(1:end-1))
hold on
idx = numTimeStepsTrain:(numTimeStepsTrain+numTimeStepsTest);
plot(idx,[data(numTimeStepsTrain) YPred],'k.-'),hold on
plot(idx,data(numTimeStepsTrain:end-1),'r'),hold on
hold off
xlabel("Day")
ylabel("P")
title("Forecast")
legend(["Observed" "Forecast"])
%% 重置网络
net = resetState(net);
net = predictAndUpdateState(net,XTrain);
YPred = [];
numTimeStepsTest = numel(XTest);
for i = 1:numTimeStepsTest
[net,YPred(:,i)] = predictAndUpdateState(net,XTest(:,i),'ExecutionEnvironment','cpu');
end
%% 反归一化
YPred = sig * YPred + mu;
%% 绘图
figure
plot(dataTrain(1:end-1))
hold on
idx = numTimeStepsTrain:(numTimeStepsTrain+numTimeStepsTest);
plot(idx,[data(numTimeStepsTrain) YPred],'k.-'),hold on
plot(idx,data(numTimeStepsTrain:end-1),'r'),hold on
hold off
xlabel("Day")
ylabel("P")
title("Forecast")
legend(["Observed" "Forecast"])