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
相关产品推荐
相关产品推荐

