为时间序列预测的PyTorch LSTM模型添加CNN层遇维度错误求助
问题描述
输入张量尺寸为[16, 15, 2],其中16是批量大小,15是时间步,2是特征数,模型需支持1或3步未来预测。添加CNN层后出现报错:
RuntimeError: Given groups=1, weight of size [1, 2, 3], expected input[16, 15, 2] to have 2 channels, but got 15 channels instead
原模型代码如下:
class TorchCNN_LSTM(nn.Module): def __init__(self, input_dim, hidden_dim, h2 ,layer_dim, output_dim, dropout_prob): super(TorchCNN_LSTM, self).__init__() ..... # CNN layer self.conv = nn.Conv1d(input_dim, output_dim, kernel_size=(3,), padding=2) # LSTM layers self.lstm = nn.LSTM( input_dim, hidden_dim, layer_dim, batch_first=True, dropout=dropout_prob ) # Fully connected layer self.fc_1 = nn.Linear(hidden_dim, h2) # fully connected self.fc_2 = nn.Linear(h2, output_dim) # fully connected last layer self.relu = nn.ReLU() def forward(self, x): #this is my trying to reshap. but id doesn't work. #x_out= x.view(len(x), 1, -1) #and #x = x.permute(0,2,1) # Initializing hidden state for first input with zeros h0 = torch.zeros(self.layer_dim, x.size(0), self.hidden_dim , device = x.device ).requires_grad_() # Initializing cell state for first input with zeros c0 = torch.zeros(self.layer_dim, x.size(0), self.hidden_dim, device=x.device).requires_grad_() out = self.conv(x_out) out = self.lstm(out, (h0.detach(), c0.detach())) out = out[:, -1, :] out = self.fc_1(out) # first dense out = self.relu(out) # relu out = self.fc_2(out) # final output return out
解决方案
错误核心原因
PyTorch的nn.Conv1d要求输入维度为[batch_size, channels, sequence_length],但你的输入是[batch_size, sequence_length, channels],导致Conv1d误将时间步15识别为通道数,而实际通道数应为2,因此触发维度不匹配报错。
修正步骤
- 适配Conv1d输入维度:用
permute(0,2,1)将输入从[16,15,2]转为[16,2,15],让Conv1d正确识别通道数。 - 适配LSTM输入维度:CNN输出维度为
[batch_size, output_channels, new_seq_len],需再次用permute(0,2,1)转回[batch_size, new_seq_len, output_channels],符合LSTMbatch_first=True的输入格式。 - 修正LSTM输入参数:LSTM的输入维度应改为CNN的输出通道数(即
output_dim),而非原输入特征数input_dim。
修正后的完整代码
import torch import torch.nn as nn class TorchCNN_LSTM(nn.Module): def __init__(self, input_dim, hidden_dim, h2, layer_dim, output_dim, dropout_prob): super(TorchCNN_LSTM, self).__init__() self.layer_dim = layer_dim self.hidden_dim = hidden_dim # CNN层:input_dim为输入通道数,输出output_dim个通道 self.conv = nn.Conv1d(input_dim, output_dim, kernel_size=3, padding=2) # LSTM输入维度改为CNN的输出通道数 self.lstm = nn.LSTM( output_dim, hidden_dim, layer_dim, batch_first=True, dropout=dropout_prob ) # 全连接层 self.fc_1 = nn.Linear(hidden_dim, h2) self.fc_2 = nn.Linear(h2, output_dim) self.relu = nn.ReLU() def forward(self, x): # 转换维度适配Conv1d:[batch, seq_len, channels] -> [batch, channels, seq_len] x_conv = x.permute(0, 2, 1) # CNN前向传播,输出维度:[batch, output_dim, new_seq_len] out = self.conv(x_conv) # 转换维度适配LSTM:[batch, output_dim, new_seq_len] -> [batch, new_seq_len, output_dim] out = out.permute(0, 2, 1) # 初始化隐藏状态与细胞状态 h0 = torch.zeros(self.layer_dim, x.size(0), self.hidden_dim, device=x.device) c0 = torch.zeros(self.layer_dim, x.size(0), self.hidden_dim, device=x.device) # LSTM前向传播,仅保留输出张量 out, _ = self.lstm(out, (h0.detach(), c0.detach())) # 取最后一个时间步的输出用于预测 out = out[:, -1, :] # 全连接层输出 out = self.fc_1(out) out = self.relu(out) out = self.fc_2(out) return out
维度流转验证
- 输入x:
[16,15,2] - 适配Conv1d后:
[16,2,15] - CNN输出:
[16, output_dim, 17](序列长度计算公式:原长度 + 2*padding - kernel_size +1) - 适配LSTM后:
[16,17, output_dim] - LSTM最后时间步输出:
[16, hidden_dim] - 最终输出:
[16, output_dim](若需3步预测,将output_dim设为3即可)
内容的提问来源于stack exchange,提问作者Sadeq Al-Ahdal
相关产品推荐
相关产品推荐

