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

PyTorch张量尺寸不匹配问题求助:padding方案无效

解决PyTorch训练MaqamCNN时的张量尺寸不匹配问题

问题背景

运行MaqamCNN训练代码时,触发RuntimeError,提示张量尺寸不匹配([1439994]与[1440000]),手动调用pad_to_max_length方法填充后问题依旧。

训练代码

import torch
import torch.nn as nn
import torch.optim as optim
import torch.utils.data as data
import dataset
import model

# Define hyperparameters
batch_size = 2
learning_rate = 0.001
num_epochs = 10

# Load the dataset
train_dataset = dataset.MaqamDataset(mode='train')

# Find the maximum length of the input tensors
max_length = 0
for i in range(len(train_dataset)):
    inputs, labels = train_dataset[i]
    if inputs.shape[0] > max_length:
        max_length = inputs.shape[0]

# Pad all input tensors to the maximum length
train_dataset.pad_to_max_length(1440000)
train_loader = data.DataLoader(train_dataset, batch_size=batch_size, shuffle=True)

# Define the model
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
model = model.MaqamCNN().to(device)

criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=learning_rate)

# Train the model
for epoch in range(num_epochs):
    
    running_loss = 0.0
    for i, data in enumerate(train_loader, 0):
        inputs, labels = data
        print(inputs.shape)
        inputs = inputs.unsqueeze(1).unsqueeze(3)
        optimizer.zero_grad()
        outputs = model(inputs)
        print("Outputs shape = ", outputs.shape)
        batch_size1 = outputs.size(0)
        padding_size = max_length - outputs.size(1)
        padding = torch.zeros(batch_size1, padding_size).to(device)
        padded_outputs = torch.cat((outputs, padding), dim=1)
        loss = criterion(padded_outputs, labels)
        loss.backward()
        optimizer.step()
        running_loss += loss.item()
    print('Epoch %d, loss: %.3f' % (epoch + 1, running_loss / len(train_loader)))

# Save the model
torch.save(model.state_dict(), 'maqam_cnn.pth')

报错信息

Traceback (most recent call last):
  File "C:\Users\omari\Documents\GitHub\Classifying_Maqams\model3\train.py", line 38, in <module>
    for i, data in enumerate(train_loader, 0):
  File "C:\Users\omari\anaconda3\lib\site-packages\torch\utils\data\dataloader.py", line 521, in __next__
    data = self._next_data()
  File "C:\Users\omari\anaconda3\lib\site-packages\torch\utils\data\dataloader.py", line 561, in _next_data
    data = self._dataset_fetcher.fetch(index)  # may raise StopIteration
  File "C:\Users\omari\anaconda3\lib\site-packages\torch\utils\data\_utils\fetch.py", line 47, in fetch
    return self.collate_fn(data)
  File "C:\Users\omari\anaconda3\lib\site-packages\torch\utils\data\_utils\collate.py", line 84, in default_collate
    return [default_collate(samples) for samples in transposed]
  File "C:\Users\omari\anaconda3\lib\site-packages\torch\utils\data\_utils\collate.py", line 84, in <listcomp>
    return [default_collate(samples) for samples in transposed]
  File "C:\Users\omari\anaconda3\lib\site-packages\torch\utils\data\_utils\collate.py", line 56, in default_collate
    return torch.stack(batch, 0, out=out)
RuntimeError: stack expects each tensor to be equal size, but got [1439994] at entry 0 and [1440000] at entry 1

当前使用的pad_to_max_length方法

def pad_to_max_length(self, max_length):
    for i in range(len(self)):
        padded_data = F.pad(self.data[i][0], (0, max_length - len(self.data[i][0])), 'constant', 0)
        self.data[i] = (padded_data, self.data[i][1])

MaqamCNN模型代码

import torch.nn as nn

class MaqamCNN(nn.Module):
    def __init__(self):
        super(MaqamCNN, self).__init__()
        self.conv1 = nn.Conv2d(1, 16, kernel_size=(5, 1), stride=(1, 1), padding=(2, 0))
        self.bn1 = nn.BatchNorm2d(16)
        self.relu1 = nn.ReLU()
        self.pool1 = nn.MaxPool2d(kernel_size=(4, 1), stride=(4, 1))
        self.conv2 = nn.Conv2d(16, 32, kernel_size=(5, 1), stride=(1, 1), padding=(2, 0))
        self.bn2 = nn.BatchNorm2d(32)
        self.relu2 = nn.ReLU()
        self.pool2 = nn.MaxPool2d(kernel_size=(4, 1), stride=(4, 1))
        self.fc1 = nn.Linear(32*90000, 128)
        self.bn3 = nn.BatchNorm1d(128)
        self.relu3 = nn.ReLU()
        self.dropout = nn.Dropout(p=0.5)
        self.fc2 = nn.Linear(128, 8)

    def forward(self, x):
        x = self.conv1(x)
        x = self.bn1(x)
        x = self.relu1(x)
        x = self.pool1(x)
        x = self.conv2(x)
        x = self.bn2(x)
        x = self.relu2(x)
        x = self.pool2(x)
        print(x.shape)
        batch_size = x.size(0)
        x = x.view(batch_size, -1)
        x = self.fc1(x)
        x = self.bn3(x)
        x = self.relu3(x)
        x = self.dropout(x)
        x = self.fc2(x)
        print("x shape = ", x.shape)
        return x

解决方案

1. 修复padding逻辑,确保所有样本尺寸统一

原pad_to_max_length方法未处理样本长度超过目标长度的情况,且可能存在遍历遗漏。修改后的方法先截断过长样本,再填充不足部分:

def pad_to_max_length(self, max_length):
    import torch.nn.functional as F
    for i in range(len(self)):
        data_tensor = self.data[i][0]
        # 截断长度超过max_length的样本
        if len(data_tensor) > max_length:
            data_tensor = data_tensor[:max_length]
        # 填充长度不足的样本到max_length
        padded_data = F.pad(data_tensor, (0, max_length - len(data_tensor)), 'constant', 0)
        self.data[i] = (padded_data, self.data[i][1])

2. 更可靠的方案:在Dataset的__getitem__中处理padding

避免提前批量处理可能出现的遗漏,每次获取样本时实时处理尺寸:

import torch.nn.functional as F
import torch.utils.data as data

class MaqamDataset(data.Dataset):
    def __init__(self, mode='train', target_length=1440000):
        self.mode = mode
        self.target_length = target_length
        # 加载数据集的逻辑,比如读取self.data列表...
    
    def __getitem__(self, idx):
        inputs, labels = self.data[idx]
        # 统一处理截断和填充
        if len(inputs) > self.target_length:
            inputs = inputs[:self.target_length]
        else:
            inputs = F.pad(inputs, (0, self.target_length - len(inputs)), 'constant', 0)
        return inputs, labels
    
    def __len__(self):
        return len(self.data)

3. 修正训练代码中的loss计算逻辑

模型最后一层输出是[batch_size, 8]的类别logits,符合CrossEntropyLoss的输入要求,不需要额外padding。删除错误的padding代码:

# 原错误代码段
# batch_size1 = outputs.size(0)
# padding_size = max_length - outputs.size(1)
# padding = torch.zeros(batch_size1, padding_size).to(device)
# padded_outputs = torch.cat((outputs, padding), dim=1)
# loss = criterion(padded_outputs, labels)

# 修正后
loss = criterion(outputs, labels)

4. 统一目标长度参数

训练代码中先计算了max_length,但又手动传入1440000调用pad_to_max_length,容易导致参数不一致。建议直接使用固定目标长度,或确保计算的max_length与传入值一致。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 01:57:34