PyTorch多层Simple RNN序列预测遇输入维度错误求助
问题排查:Simple RNN输入维度不匹配错误
错误核心原因
报错RuntimeError: input.size(-1) must be equal to input_size. Expected 8, got 1的本质是RNN输入维度参数设置混淆:
- 你的数据是单特征时序,每个时间步的特征数为1,窗口长度(序列长度)为8。但你初始化模型时将
input_sz设为8,把序列长度当成了每个时间步的特征维度,导致输入张量最后一维(特征数1)和RNN期望的输入维度8不匹配。
其他需修正的问题
- Forward函数返回值错误:当前返回所有时间步的RNN输出和隐藏状态,但我们只需要最后一个时间步的输出用于预测下一个值,多余的返回值会导致训练时维度不匹配。
- 隐藏状态设备不匹配:初始化的
hidden张量未同步到输入所在设备(CPU/GPU),会引发设备不一致错误。 - Eval代码缩进错误:
continue语句会跳过后续评估逻辑,需调整缩进确保代码执行。 - 目标张量维度冗余:Y无需额外添加维度,保持
(batch_size, 1)即可匹配预测值维度。
修正后的完整代码
import torch import torch.nn as nn import torch.optim as optim import torch.utils.data as data import numpy as np # 滑动窗口构建的训练集 X = np.array( [ [0.40, 0.82, 0.14, 0.01, 0.98, 0.53, 2.5, 0.49], [0.82, 0.14, 0.01, 0.98, 0.53, 2.5, 0.49, 0.53], [0.14, 0.01, 0.98, 0.53, 2.5, 0.49, 0.53, 3.37] ], dtype=np.float32) Y = np.array([[0.53], [3.37], [0.49]], dtype=np.float32) class RNNModel(nn.Module): def __init__(self, input_sz, n_layers): super(RNNModel, self).__init__() self.hidden_dim = 3 * input_sz self.n_layers = n_layers self.output_sz = 1 # input_sz为每个时间步的特征数(单特征设为1),batch_first=True对应输入形状(batch_size, seq_len, input_sz) self.rnn = nn.RNN(input_sz, self.hidden_dim, num_layers=n_layers, batch_first=True) self.linear = nn.Linear(self.hidden_dim, self.output_sz) def forward(self, x): batch_sz = x.size(0) # 初始化隐藏状态并同步到输入所在设备 hidden = torch.zeros(self.n_layers, batch_sz, self.hidden_dim).to(x.device) out, hidden = self.rnn(x, hidden) # 取最后一个时间步的输出用于预测 out = out[:, -1, :] # 全连接层输出预测值 out = self.linear(out) return out device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") # input_sz改为1,对应单特征时序 model = RNNModel(1, 2).to(device) # X添加特征维度,形状变为(batch_size, seq_len, input_sz)=(3,8,1) X = torch.tensor(X[:, :, np.newaxis]).to(device) # Y保持(batch_size, 1)维度即可 Y = torch.tensor(Y).to(device) optimizer = optim.Adam(model.parameters()) loss_fn = nn.MSELoss() loader = data.DataLoader(data.TensorDataset(X, Y), shuffle=False, batch_size=3) n_epoch = 10 for epoch in range(n_epoch): model.train() total_loss = 0.0 for X_batch, Y_batch in loader: Y_pred = model(X_batch) loss = loss_fn(Y_pred, Y_batch) optimizer.zero_grad() loss.backward() optimizer.step() total_loss += loss.item() # 调整条件与缩进,确保评估代码正常执行 if epoch % 10 == 0: model.eval() with torch.no_grad(): Y_pred = model(X) train_rmse = np.sqrt(loss_fn(Y_pred, Y).item()) print(f"Epoch {epoch}: train RMSE {train_rmse:.4f}")
关键修正点说明
- RNN输入维度修正:将
RNNModel(8,2)改为RNNModel(1,2),匹配单特征时序的每个时间步特征数。 - Forward函数优化:
- 隐藏状态初始化时添加
.to(x.device),确保与输入设备一致。 - 提取最后一个时间步的输出
out[:, -1, :],用于预测下一个时序值。 - 移除多余的隐藏状态返回,直接输出预测值。
- 隐藏状态初始化时添加
- Eval逻辑修复:调整条件判断与缩进,让评估代码能正常触发执行。
- 目标张量简化:Y不再添加冗余维度,保证与预测值维度匹配。
内容的提问来源于stack exchange,提问作者Shew
相关产品推荐
相关产品推荐

