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

PyTorch LSTM回归模型维度错误排查:无法输出模型结果

问题排查与修正方案

1. 输入维度适配(解决LSTM 3D输入要求)

你的X_train是(69010,14)的2D张量,但LSTM要求输入必须是**(批量大小, 序列长度, 特征数)**的3D格式。回归任务用LSTM本质是序列预测,需要先把单步特征数据转换为序列样本:

import numpy as np
import pandas as pd

def create_sequences(data, seq_len, target_col_idx):
    X, y = [], []
    # 用过去seq_len个时间步的特征预测当前营收
    for i in range(len(data) - seq_len):
        X.append(data.iloc[i:i+seq_len, :-1].values)
        y.append(data.iloc[i+seq_len, target_col_idx])
    return np.array(X), np.array(y)

# 假设合并后的训练数据集为train_df,最后一列是营收目标
X_train_seq, y_train_seq = create_sequences(train_df, seq_len=24, target_col_idx=-1)
# 转换后X_train_seq形状为(样本数, 24, 14),符合LSTM输入要求

如果确实不需要序列逻辑(但没必要用LSTM),也可以临时给每个样本加长度为1的序列维度:

X_train = X_train.unsqueeze(1)  # 形状变为(69010,1,14)

2. 修正RevenuePredictor模型的核心错误

针对你提到的3个模型问题,直接给出修正后的代码:

固定序列长度场景(无需处理变长序列)

这是最常见的场景,去掉冗余的packed序列处理,避免索引错误:

import torch
import torch.nn as nn

class RevenuePredictor(nn.Module):
    def __init__(self, input_size, hidden_size, num_layers, output_size):
        super().__init__()
        self.hidden_size = hidden_size
        self.num_layers = num_layers
        # batch_first=True 让输入维度为(batch, seq_len, input_size)
        self.lstm = nn.LSTM(input_size, hidden_size, num_layers, batch_first=True)
        self.fc = nn.Linear(hidden_size, output_size)
    
    def forward(self, x):
        # x shape: (batch_size, seq_len, input_size)
        _, (h_n, _) = self.lstm(x)
        # 取LSTM最后一层的隐藏状态作为全连接层输入
        out = self.fc(h_n[-1, :, :])
        return out

变长序列场景(需处理不同长度的序列)

如果必须处理变长序列,修正packed序列和索引错误:

class RevenuePredictor(nn.Module):
    def __init__(self, input_size, hidden_size, num_layers, output_size):
        super().__init__()
        self.hidden_size = hidden_size
        self.num_layers = num_layers
        self.lstm = nn.LSTM(input_size, hidden_size, num_layers, batch_first=True)
        self.fc = nn.Linear(hidden_size, output_size)
    
    def forward(self, x, lengths):
        batch_size = x.size(0)
        # 按序列长度降序排序,适配pack_padded_sequence要求
        sorted_lengths, sorted_idx = torch.sort(lengths, descending=True)
        x_sorted = x[sorted_idx]
        
        # 打包序列
        packed_x = nn.utils.rnn.pack_padded_sequence(x_sorted, sorted_lengths.cpu(), batch_first=True)
        packed_out, (h_n, _) = self.lstm(packed_x)
        
        # 取最后一层隐藏状态并恢复原样本顺序
        h_n = h_n[-1, :, :]
        unsorted_idx = torch.argsort(sorted_idx)
        h_n_unsorted = h_n[unsorted_idx]
        
        out = self.fc(h_n_unsorted)
        return out

3. 训练循环修正

固定序列长度的训练循环

device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model = RevenuePredictor(input_size=14, hidden_size=64, num_layers=2, output_size=1).to(device)
criterion = nn.MSELoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)

batch_size = 32
epochs = 10

for epoch in range(epochs):
    model.train()
    running_loss = 0.0
    for i in range(0, len(X_train_seq), batch_size):
        batch_x = torch.tensor(X_train_seq[i:i+batch_size], dtype=torch.float32).to(device)
        # 给y增加维度,匹配模型输出的(32,1)形状
        batch_y = torch.tensor(y_train_seq[i:i+batch_size], dtype=torch.float32).unsqueeze(1).to(device)
        
        optimizer.zero_grad()
        outputs = model(batch_x)
        loss = criterion(outputs, batch_y)
        loss.backward()
        optimizer.step()
        
        running_loss += loss.item() * batch_x.size(0)
    
    epoch_loss = running_loss / len(X_train_seq)
    print(f'Epoch {epoch+1}/{epochs}, Loss: {epoch_loss:.4f}')

变长序列的训练注意点

如果用变长序列模型,lengths不能是全1张量,必须是每个样本的实际有效序列长度(比如样本前面补0,有效长度为N),训练时传入该参数即可。

解决RuntimeError: input must have 2 dimensions, got 1

这个错误通常是因为:

  • 目标变量y_train是1D张量(69010),需要转为2D(69010,1):y_train = y_train.unsqueeze(1)
  • 模型输出的维度与目标变量不匹配,确保输出层是Linear(hidden_size, 1),输出为(batch_size,1)的2D张量

内容的提问来源于stack exchange,提问作者Aurimas Nausėdas

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 08:59:20