MATLAB LSTM 训练集上的拟合还能看出效果,但预测部分无论怎么调参数都总是会变成一条直线

刚接触LSTM,问题困扰了我很久,麻烦各位帮忙看下,快给整自闭了


%% 定义训练集与测试集
[m,n]=size(Initialdata);
zoom = 1000;                         %缩放数据集
n = floor(n/zoom);
data = zeros(1,n);
for i = 1:n
    data(1,i) = Initialdata(1,i*zoom);
end
n1=round(n*0.5);                   %划分数据集
dataTrain = data(1:n1);            %定义训练集
dataTest = data(:,n1+1:n);         %该数据是用来在最后与预测值进行对比的
%% 数据预处理
mu = mean(dataTrain);              %求均值 
sig = std(dataTrain);              %求均差 
dataTrainStandardized = (dataTrain - mu) / sig;    %求单位标准差
%% 构建滑动窗口
step = 2;                                    % 步长
pre = 5000;                                          %对未来预测的步数
XTrain = zeros(step,n1-step);
count = 1;                                 
XTrainColumn = 1;                      % 标志XTrain中的当前存储列数

for r = 1:n1-step
    for h = 1:step
        XTrain(count,XTrainColumn) = dataTrainStandardized(r+h-1);
        count = count + 1;
    end
    XTrainColumn = XTrainColumn + 1;    % 一次滑窗结束后,当前存储行数、count位、滑窗的开始结束位置都发生改变
    count = 1;
end 
YTrain = dataTrainStandardized(step+1:end);  
%% 建立LSTM
numFeatures = step;   %特征维度与滑动窗口大小一致
numResponses = 1;     %输出为一维
numHiddenUnits = 10;   %创建LSTM回归网络,指定LSTM层的隐含单元个数。可调
 
layers = [
    sequenceInputLayer(numFeatures,"Normalization","zscore")
    lstmLayer(3)
    dropoutLayer(0.9)
    fullyConnectedLayer(numResponses)
    regressionLayer];     % 回归输出
 

options = trainingOptions('adam', ...       %求解器设置为adam
    'MaxEpochs',300, ...                    %训练轮数
    'GradientThreshold',1, ...              %梯度阈值
    'InitialLearnRate',0.05, ...             %指定初始学习率
    'LearnRateSchedule','piecewise', ...    %每当经过一定数量的时期时,学习率就会乘以一个系数。
    'LearnRateDropPeriod',1000, ...          %乘法之间的纪元数由“ LearnRateDropPeriod”控制。可调
    'LearnRateDropFactor',0.5, ...         %乘法因子由参“ LearnRateDropFactor”控制,可调。在 LearnRateDropPeriod 轮训练后通过乘以因子 LearnRateDropFactor 来降低学习率                                            
    'Verbose',0,  ...                       %如果将其设置为true,则有关训练进度的信息将被打印到命令窗口中。默认值为true
    'Plots','training-progress');           %构建曲线图。关闭则将'training-progress'替换为none
net = trainNetwork(XTrain,YTrain,layers,options);      %使用以上LSTM参数对指定训练集进行训练
%% 进行用于验证神经网络的数据预测(用预测值更新网络状态)

net = predictAndUpdateState(net,XTrain);
for i = 1 : n1-step
    x=XTrain(:,i);
    [net,y] = predictAndUpdateState(net,x,'MiniBatchSize',1);    %YPlot为LSTM训练集所得参数
    YPlot(:,i)=y;
end                                                               

count = 1;  
for i = 1: step
    XTrain(i,n1-step+1) = dataTrainStandardized(:,n1-step+i);
end
for r=1:n-n1+pre
     for h = 1:step-1
         XTrain(count,n1-step+r+1) = XTrain(count+1,n1-step+r);
         count = count + 1;
     end
     x=XTrain(:,n1-step+r);
     [net,y] = predictAndUpdateState(net,x,'MiniBatchSize',1);
     YPlot(:,n1-step+r)=y;
     XTrain(count,n1-step+r+1) = YPlot(:,n1-step+r);
     count = 1;
end


%% 验证神经网络
YPlot = sig*YPlot + mu;                            %使用先前计算的参数对预测去标准化。
rmse = sqrt(mean((YPlot(n1-step+1:end-pre)-dataTest).^2)) ;     %计算均方根误差 (RMSE)。
subplot(2,1,1)
plot(YPlot(1:n1-step))                               %画出训练数据
hold on
idx = n1+1:n;                                        %横坐标
plot(idx,YPlot(n1-step+1:end-pre),'.-')                         %显示预测值
hold off
xlabel("Time")
ylabel("Case")
title("Forecast")
legend(["Observed" "Forecast"])
subplot(2,1,2)
plot(data)
xlabel("Time")
ylabel("Case")
title("Dataset")


img

Observed是训练集经过LSTM拟合得到的,Forecast是用上一个时间步长的LSTM输出作为新输入得到的

img

可以尝试增加LSTM层的隐含单元个数numHiddenUnits,或者调整学习率看看