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

PyTorch LSTM测试预测值恒定、训练预测值递增问题排查

问题原因分析

针对你遇到的LSTM模型异常,主要原因可归纳为以下几点:

  1. 输出层设计错误
    若模型仅对LSTM的最后一个时间步输出做全连接变换,再重复填充到4个时间步,会导致每个样本的4个时间步预测值完全相同。这种错误常见于对序列输出逻辑的理解偏差,未对LSTM每个时间步的隐藏状态单独映射。

  2. 数据未做归一化处理
    特征或标签的数值范围过大时,模型难以学习到序列依赖关系,会趋向输出训练集标签的均值(23.9606大概率是Y_train的均值)——这是模型在无法捕捉有效模式时,最小化MSE损失的“惰性”选择。同时未归一化的数据也可能导致训练时梯度爆炸/消失,使预测值持续偏离。

  3. 损失函数计算逻辑错误
    若训练时未对每个时间步的预测值与真实值计算损失(例如仅计算最后一个时间步的损失),模型会忽略序列时间维度的依赖,最终输出恒定值。此外损失函数的方向错误(如误将损失设为负向)也会导致预测值持续升高。

  4. 模型容量不足或梯度问题
    LSTM的隐藏层维度(hidden_size)过小、层数不足,会导致模型无法拟合序列的复杂模式;优化器学习率设置不当(过大导致震荡,过小导致无法收敛)、梯度未正确回传,也会使模型停留在无效的恒定输出状态。

修正方案

1. 修正模型输出层结构

确保LSTM每个时间步的隐藏状态都经过独立的全连接层映射,输出与标签匹配的(batch_size, 4, 1)维度:

import torch
import torch.nn as nn

class SeqLSTM(nn.Module):
    def __init__(self, input_size=7, hidden_size=64, num_layers=2):
        super().__init__()
        self.lstm = nn.LSTM(input_size, hidden_size, num_layers, batch_first=True)
        self.fc = nn.Linear(hidden_size, 1)  # 对每个时间步的隐藏状态做映射

    def forward(self, x):
        # x shape: (batch_size, seq_len, input_size)
        lstm_out, _ = self.lstm(x)  # lstm_out shape: (batch_size, 4, hidden_size)
        output = self.fc(lstm_out)  # output shape: (batch_size, 4, 1)
        return output

2. 对数据进行归一化

将特征和标签缩放到[0,1]或[-1,1]范围,消除数值差异对模型的影响,训练完成后再反归一化还原真实值:

from sklearn.preprocessing import MinMaxScaler

# 处理训练集特征
scaler_x = MinMaxScaler(feature_range=(0,1))
# 先reshape为(样本数*时间步, 特征数),再归一化
x_train_reshaped = X_train.reshape(-1, 7)
x_train_scaled = scaler_x.fit_transform(x_train_reshaped).reshape(24433, 4, 7)

# 处理训练集标签
scaler_y = MinMaxScaler(feature_range=(0,1))
y_train_reshaped = Y_train.reshape(-1, 1)
y_train_scaled = scaler_y.fit_transform(y_train_reshaped).reshape(24433, 4, 1)

# 测试集使用训练集的归一化器,避免数据泄露
x_test_reshaped = X_test.reshape(-1, 7)
x_test_scaled = scaler_x.transform(x_test_reshaped).reshape(6109, 4, 7)

3. 修正损失计算与训练逻辑

确保损失函数对每个时间步的预测值和真实值计算,同时规范训练流程:

model = SeqLSTM()
criterion = nn.MSELoss()
optimizer = torch.optim.Adam(model.parameters(), lr=1e-3)

# 转换为PyTorch张量
x_train_tensor = torch.tensor(x_train_scaled, dtype=torch.float32)
y_train_tensor = torch.tensor(y_train_scaled, dtype=torch.float32)

epochs = 50
for epoch in range(epochs):
    model.train()
    optimizer.zero_grad()
    
    outputs = model(x_train_tensor)
    loss = criterion(outputs, y_train_tensor)
    
    loss.backward()
    optimizer.step()
    
    if (epoch+1) % 5 == 0:
        print(f'Epoch [{epoch+1}/{epochs}], Loss: {loss.item():.4f}')

4. 调整模型与优化器参数

  • 增大LSTM的hidden_size(如从32调整到64或128),或增加层数(如num_layers=2)提升模型容量;
  • 调整学习率:若训练损失震荡,可将学习率降至1e-4;若损失下降缓慢,可尝试5e-3;
  • 训练时打乱数据集:使用DataLoader加载数据并设置shuffle=True,避免模型学习到数据的顺序偏差。

测试阶段的正确处理

测试时关闭梯度计算,反归一化得到真实预测值:

model.eval()
x_test_tensor = torch.tensor(x_test_scaled, dtype=torch.float32)

with torch.no_grad():
    test_outputs = model(x_test_tensor)
    # 反归一化还原真实值
    test_outputs_reshaped = test_outputs.numpy().reshape(-1, 1)
    test_preds = scaler_y.inverse_transform(test_outputs_reshaped).reshape(6109, 4, 1)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 18:31:45