You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

LSTM多对一架构时间序列预测结果严重偏离问题求助

问题:LSTM多对一预测结果严重偏离实际值

用12个月的序列预测12个月的数据,采用many-to-one LSTM架构,输出12维向量。但预测结果与预期偏差极大:时间序列实际值约为0.96,预测值却仅在0.08-0.12区间内;即使将epochs增加到1000,预测最大值仍仅约为0.2。

生成72个随机值后,使用subsequences函数创建长度为12的重叠序列,X维度为[12时间步序列数量, 12, 1],代码实现如下:

from keras.models import Sequential
from keras.layers import LSTM
from keras.layers import Dense
import numpy as np
import pandas as pd

def subsequences(ts, window):
    shape = (ts.size - window + 1, window)
    strides = ts.strides * 2
    return np.lib.stride_tricks.as_strided(ts, shape=shape, strides=strides)

test_arr = np.random.normal(0.975, 0.008, size=72)

ts = 12

temp = subsequences(test_arr, ts)
X = temp.reshape(temp.shape[0], temp.shape[1], 1)
y = subsequences(pd.Series(test_arr).shift(-ts).to_numpy(), ts)

X_predict = X[-ts, :, :]

# Lop off the timestamps that have missing values
X = X[:(X.shape[0] - ts - 1), :, :]
y = y[:(y.shape[0] - ts - 1), :]

output = 12

model = Sequential()
model.add(LSTM(12, return_sequences=True, input_shape=(ts, 1)))
model.add(LSTM(12))
model.add(Dense(output))
model.compile(loss='mae', optimizer='adam')
model.summary()

model.fit(X, y, batch_size = 24, epochs = 50)

yhat = model.predict(X_predict, verbose=0)

部分预测结果如下:

array([[0.11727975, 0.08559777, 0.09116013, 0.09350648, 0.13221847,
        0.08328149, 0.12618074, 0.12006135, 0.11579201, 0.10330589,
        0.11863852, 0.13914064],
       [0.1172842 , 0.08561642, 0.091188  , 0.0935307 , 0.1322322 ,
        0.08330169, 0.12619175, 0.12007872, 0.11579723, 0.10331573,
        0.11865252, 0.13916571],
       [0.11731011, 0.08572483, 0.09135018, 0.09367174, 0.13231221,
        0.08341929, 0.12625587, 0.12017974, 0.1158275 , 0.10337301,
        0.11873408, 0.13931161],

核心问题排查与修正方案

1. 标签y的生成逻辑错误

原代码中用shift(-ts)+subsequences生成y的逻辑完全错误:shift(-12)会让原数组最后12个值变为NaN,再用subsequences处理会生成包含无效值的序列,后续截断操作进一步打乱了X与y的对应关系,导致模型根本无法学习到正确的输入输出映射。

正确的y应该是每个X对应的未来12个连续值,直接通过切片生成即可:

# 替换原y的生成代码
y = np.array([test_arr[i+ts:i+ts+output] for i in range(len(X))])

2. 不必要的数据截断导致训练样本不足

原代码中X = X[:(X.shape[0] - ts - 1), :, :]和y = y[:(y.shape[0] - ts - 1), :]的截断操作完全多余,大幅减少了有效训练样本。正确的样本量应为len(test_arr) - ts - output + 1 = 72-12-12+1=49个。

3. 未做数据归一化

数据分布在0.96左右,属于连续值回归任务,但未做归一化处理,LSTM的输出范围难以匹配原始数据尺度,导致预测值被压缩到小区间。建议用MinMaxScaler将数据缩至0-1区间,训练后再反归一化得到真实值。

4. 训练参数不合理

  • batch_size设为24,远大于有效样本量,导致每个epoch的参数更新次数极少,模型收敛缓慢,建议调小至8或16;
  • 可加入早停(EarlyStopping)回调函数,防止模型过拟合,同时自动停止无效训练。

修正后的完整代码示例

from keras.models import Sequential
from keras.layers import LSTM, Dense
from keras.callbacks import EarlyStopping
import numpy as np
from sklearn.preprocessing import MinMaxScaler

def create_sequences(data, input_len, output_len):
    X, y = [], []
    # 确保每个X都有对应的完整y序列
    for i in range(len(data) - input_len - output_len + 1):
        X.append(data[i:i+input_len])
        y.append(data[i+input_len:i+input_len+output_len])
    return np.array(X), np.array(y)

# 生成原始数据
test_arr = np.random.normal(0.975, 0.008, size=72)
# 数据归一化
scaler = MinMaxScaler(feature_range=(0, 1))
scaled_data = scaler.fit_transform(test_arr.reshape(-1, 1))

input_len = 12
output_len = 12

# 创建训练序列
X, y = create_sequences(scaled_data, input_len, output_len)
# 调整X维度为[样本数, 时间步, 特征数]
X = X.reshape(X.shape[0], X.shape[1], 1)

# 构建模型
model = Sequential()
model.add(LSTM(12, return_sequences=True, input_shape=(input_len, 1)))
model.add(LSTM(12))
model.add(Dense(output_len))
model.compile(loss='mae', optimizer='adam')

# 早停回调:验证集损失10轮不下降则停止,恢复最优权重
early_stop = EarlyStopping(monitor='val_loss', patience=10, restore_best_weights=True)
# 划分训练/验证集
split = int(0.8 * len(X))
X_train, X_val = X[:split], X[split:]
y_train, y_val = y[:split], y[split:]

# 训练模型
model.fit(X_train, y_train, 
          validation_data=(X_val, y_val),
          batch_size=8, 
          epochs=500,
          callbacks=[early_stop])

# 准备预测用的输入序列(最后12个归一化后的数据)
X_predict = scaled_data[-input_len:].reshape(1, input_len, 1)
# 预测并反归一化得到真实值
yhat = model.predict(X_predict, verbose=0)
yhat = scaler.inverse_transform(yhat).flatten()
print(yhat)

内容的提问来源于stack exchange,提问作者matsuo_basho

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 17:07:49