clc
clear
data=readtable("第三问.xlsx");
data = table2array(data(:, 1))'; %不转置的话,无法训练lstm网络,显示维度不对。
totalDataSize = length(data); % 获取数据总大小
trainRatio = 0.75; % 定义训练集占比,比如75%
trainSize = floor(totalDataSize * trainRatio); % 计算训练集大小
dataTrain = data(1:trainSize); % 定义训练集
dataTest = data(trainSize + 1:end); % 剩下的数据为测试集
%% 数据预处理
mu = mean(dataTrain); %求均值
sig = std(dataTrain); %求均差
dataTrainStandardized = (dataTrain - mu) / sig;
%% 输入的每个时间步,LSTM网络学习预测下一个时间步,这里交错一个时间步效果最好。
XTrain = dataTrainStandardized(1:end-1);
YTrain = dataTrainStandardized(2:end);
%% 一维特征lstm网络训练
numFeatures = 1; %特征为一维
numResponses = 1; %输出也是一维
numHiddenUnits = 20; %创建LSTM回归网络,指定LSTM层的隐含单元个数200。可调
layers = [ ...
sequenceInputLayer(numFeatures) %输入层
lstmLayer(numHiddenUnits) % lstm层,如果是构建多层的LSTM模型,可以修改。
fullyConnectedLayer(numResponses) %为全连接层,是输出的维数。
regressionLayer]; %其计算回归问题的半均方误差模块 。即说明这不是在进行分类问题。
%指定训练选项,求解器设置为adam, 1000轮训练。
%梯度阈值设置为 1。指定初始学习率 0.01,在 125 轮训练后通过乘以因子 0.2 来降低学习率。
options = trainingOptions('adam', ...
'MaxEpochs',100, ...
'GradientThreshold',1, ...
'InitialLearnRate',0.01, ...
'LearnRateSchedule','piecewise', ...%每当经过一定数量的时期时,学习率就会乘以一个系数。
'LearnRateDropPeriod',400, ... %乘法之间的纪元数由“ LearnRateDropPeriod”控制。可调
'LearnRateDropFactor',0.15, ... %乘法因子由参“ LearnRateDropFactor”控制,可调
'Verbose',0, ... %如果将其设置为true,则有关训练进度的信息将被打印到命令窗口中。默认值为true。
'Plots','training-progress'); %构建曲线图 将'training-progress'替换为none
net = trainNetwork(XTrain,YTrain,layers,options);
net = predictAndUpdateState(net,XTrain); %将新的XTrain数据用在网络上进行初始化网络状态
[net,YPred] = predictAndUpdateState(net,YTrain(end));
%用训练的最后一步来进行预测第一个预测值,给定一个初始值。这是用预测值更新网络状态特有的。
%% 进行用于验证神经网络的数据预测(用预测值更新网络状态)
for i = 150:197 %从第二步开始,这里进行191次单步预测(191为用于验证的预测值,100为往后预测的值。一共291个)
[net,YPred(:,i)] = predictAndUpdateState(net,YPred(:,i-1),'ExecutionEnvironment','cpu'); %predictAndUpdateState函数是一次预测一个值并更新网络状态
end
%% 验证神经网络
YPred = sig*YPred + mu; % 使用先前计算的参数对预测去标准化。
rmse = sqrt(mean((YPred(150:197) - dataTest).^2)); % 计算均方根误差 (RMSE)。
fprintf('Root Mean Square Error (RMSE): %f\n', rmse); % 打印 RMSE
% 绘制预测结果
figure;
subplot(2,1,1)
plot(dataTrain(1:end)); % 绘制训练数据
hold on
idx = 150:(197 + length(dataTest) - 1); % 为横坐标
plot(idx, YPred(150:197), '.-'); % 显示预测值
hold off
xlabel("Time")
ylabel("Case")
title("Forecast")
legend(["Observed" "Forecast"])
subplot(2,1,2)
plot(dataTest); % 绘制测试数据
xlabel("Time")
ylabel("Case")
title("Dataset")
%% 继续往后预测2023年的数据
figure;
idx = 1:197; % 为横坐标
plot(idx, YPred(1:197), '.-'); % 显示预测值
hold off
xlabel("Time")
ylabel("Case")
title("2023 Forecast")
% 注意:确保 YPred(1:25) 的长度与 idx 匹配,并且预测值是按照您的需求计算得到的。
这是我的代码,我现在有197组数据,我把前150项当做训练集,150-197为测试集,我想预测未来的20次数据,现在这个代码只能出来训练过程这个图,如图片所示,只能运行出来上面那个图,下面的图都出不来