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

1D CNN多元时间序列预测模型维度不匹配问题排查求助

1D CNN多元时间序列预测模型维度不匹配问题排查

问题背景

使用household_power_consumption.txt数据集做多元时间序列预测,数据配置为batch size=64、序列长度=50、7个特征,已完成预处理。实现1D CNN模型后运行报错,错误信息如下:

Traceback (most recent call last):

  Cell In[15], line 73
    Train()

  Cell In[15], line 41 in Train
    preds = model(inputs.float())

  File ~\anaconda3\Lib\site-packages\torch\nn\modules\module.py:1501 in _call_impl
    return forward_call(*args, **kwargs)

  Cell In[15], line 17 in forward
    x = self.fc1(x)

  File ~\anaconda3\Lib\site-packages\torch\nn\modules\module.py:1501 in _call_impl
    return forward_call(*args, **kwargs)

  File ~\anaconda3\Lib\site-packages\torch\nn\modules\linear.py:114 in forward
    return F.linear(input, self.weight, self.bias)

RuntimeError: mat1 and mat2 shapes cannot be multiplied (64x1400 and 200x100)

原模型代码:

import torch
import torch.nn as nn
import gc

class CNN_ForecastNet(nn.Module):
    def __init__(self):
        super(CNN_ForecastNet,self).__init__()
        self.conv1d = nn.Conv1d(50,200,kernel_size=1)
        self.relu = nn.ReLU(inplace=True)
        self.drop_out = nn.Dropout(0.5)
        self.max_pooling = nn.MaxPool1d(1)
        self.fc1 = nn.Linear(200,100)
        self.fc2 = nn.Linear(100,1)
        
    def forward(self,x):
        x = self.conv1d(x)
        x = self.relu(x)
        x = self.drop_out(x)
        x = self.max_pooling(x)
        x = x.view(x.size(0),-1)
        x = self.fc1(x)
        x = self.relu(x)
        x = self.fc2(x)
        
        return x
    
    
model = CNN_ForecastNet()
train_losses = []
valid_losses = []
def Train():
    
    running_loss = .0
    
    model.train()
    
    for idx, (inputs,labels) in enumerate(train_loader):
        optimizer.zero_grad()
        preds = model(inputs.float())
        loss = criterion(preds,labels)
        loss.backward()
        optimizer.step()
        running_loss += loss
        
    train_loss = running_loss/len(train_loader)
    train_losses.append(train_loss.detach().numpy())
    
    print(f'train_loss {train_loss}')
    
def Valid():
    running_loss = .0
    
    model.eval()
    
    with torch.no_grad():
        for idx, (inputs, labels) in enumerate(test_loader):
            optimizer.zero_grad()
            preds = model(inputs.float())
            loss = criterion(preds,labels)
            running_loss += loss
            
        valid_loss = running_loss/len(test_loader)
        valid_losses.append(valid_loss.detach().numpy())
        print(f'valid_loss {valid_loss}')

epochs = 10
for epoch in range(epochs):
  if epoch % 2==0:

    print('epochs {}/{}'.format(epoch+1,epochs))
    Train()
    Valid()
    gc.collect()

问题分析

错误核心是维度不匹配,根源有两点:

  1. Conv1D参数与输入格式不匹配:PyTorch中nn.Conv1d要求输入格式为(batch_size, in_channels, sequence_length),其中in_channels是特征数(这里是7),而非序列长度(50)。原代码把序列长度设为输入通道数,且输入数据大概率是(batch_size, sequence_length, features)(即(64,50,7)),未转置为Conv1D需要的(64,7,50),导致Conv1D输出维度为(64,200,7),展平后是64×1400,和全连接层fc1(200,100)的输入要求不匹配。
  2. 池化层无效:MaxPool1d(1)不会改变序列维度,无法将时序特征压缩到固定长度,进一步导致展平后的维度和全连接层不兼容。

修正方案

1. 调整Conv1D参数与输入维度

将Conv1d的in_channels改为特征数7,同时在forward中先转置输入,把(batch, seq_len, features)转为(batch, features, seq_len)。

2. 替换池化层为自适应池化

用AdaptiveMaxPool1d(1)将序列维度压缩为1,展平后得到(batch, 200),刚好匹配fc1的输入维度。

修正后的模型代码:

import torch
import torch.nn as nn
import gc

class CNN_ForecastNet(nn.Module):
    def __init__(self):
        super(CNN_ForecastNet,self).__init__()
        # 修正in_channels为特征数7,可选调整kernel_size提升时序特征捕捉能力
        self.conv1d = nn.Conv1d(7,200,kernel_size=3, padding=1)
        self.relu = nn.ReLU(inplace=True)
        self.drop_out = nn.Dropout(0.5)
        # 自适应池化将序列维度压缩到1
        self.adaptive_pool = nn.AdaptiveMaxPool1d(1)
        self.fc1 = nn.Linear(200,100)
        self.fc2 = nn.Linear(100,1)
        
    def forward(self,x):
        # 转置输入适配Conv1D格式
        x = x.transpose(1, 2)
        x = self.conv1d(x)
        x = self.relu(x)
        x = self.drop_out(x)
        x = self.adaptive_pool(x)
        # 展平为(batch, 200)
        x = x.view(x.size(0),-1)
        x = self.fc1(x)
        x = self.relu(x)
        x = self.fc2(x)
        
        return x
    
    
model = CNN_ForecastNet()
train_losses = []
valid_losses = []
def Train():
    
    running_loss = .0
    
    model.train()
    
    for idx, (inputs,labels) in enumerate(train_loader):
        optimizer.zero_grad()
        preds = model(inputs.float())
        loss = criterion(preds,labels)
        loss.backward()
        optimizer.step()
        running_loss += loss
        
    train_loss = running_loss/len(train_loader)
    train_losses.append(train_loss.detach().numpy())
    
    print(f'train_loss {train_loss}')
    
def Valid():
    running_loss = .0
    
    model.eval()
    
    with torch.no_grad():
        for idx, (inputs, labels) in enumerate(test_loader):
            optimizer.zero_grad()
            preds = model(inputs.float())
            loss = criterion(preds,labels)
            running_loss += loss
            
        valid_loss = running_loss/len(test_loader)
        valid_losses.append(valid_loss.detach().numpy())
        print(f'valid_loss {valid_loss}')

epochs = 10
for epoch in range(epochs):
  if epoch % 2==0:

    print('epochs {}/{}'.format(epoch+1,epochs))
    Train()
    Valid()
    gc.collect()

额外说明

  • 若输入数据已经是(batch, features, seq_len)格式,可去掉x = x.transpose(1,2)这一行。
  • 原代码中kernel_size=1的Conv1D效果接近全连接层,调整为更大的kernel_size(如3、5)并添加padding,能更好捕捉时序特征的局部关联。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 02:47:08