【问题标题】:PyTorch mat1 and mat2 shapes cannot be multiplied (4x460800 and 80000x16)PyTorch mat1 和 mat2 形状不能相乘(4x460800 和 80000x16)
【发布时间】:2022-08-22 19:15:49
【问题描述】:

我正在尝试使用 PyTorch 查找道路车道。我创建了数据集和我的模型。但是当我尝试训练我的模型时,我得到mat1 and mat2 shapes cannot be multiplied (4x460800 and 80000x16) 错误。我尝试过其他主题的解决方案,但这些解决方案对我帮助不大。

我的数据集是一堆带有验证图像的道路图像。我有 .csv 文件,其中包含图像名称(例如 \'image1.jpg、image2.jpg\')。图像和验证图像的原始尺寸为 1280x720。我在我的数据集代码中将它们转换为 200x200。

道路图:

验证图片:

这是我的数据集:

import os
import pandas as pd
import random

import torch
import torchvision.transforms.functional as TF
from torch.utils.data import Dataset
from torchvision import transforms
from PIL import Image

class Dataset(Dataset):
    def __init__(self, csv_file, root_dir, val_dir, transform=None):
        self.annotations = pd.read_csv(csv_file)
        self.root_dir = root_dir
        self.val_dir = val_dir
        self.transform = transform

    def __len__(self):
        return len(self.annotations)

    def __getitem__(self, index):
        img_path = os.path.join(self.root_dir, self.annotations.iloc[index, 0])
        image = Image.open(img_path).convert(\'RGB\')
        mask_path = os.path.join(self.val_dir, self.annotations.iloc[index, 0])
        mask = Image.open(mask_path).convert(\'RGB\')

        transform = transforms.Compose([
            transforms.Resize((200, 200)), 
            transforms.ToTensor()
        ])

        if self.transform:
            image = self.transform(image)
            mask = self.transform(mask)

        return image, mask

我的模型:

import torch
import torch.nn as nn

class Net(nn.Module):
    def __init__(self):
        super().__init__()

        self.cnn_layers = nn.Sequential(
            # Conv2d, 3 inputs, 128 outputs
            # 200x200 image size
            nn.Conv2d(3, 128, kernel_size=3, stride=1, padding=1),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=2, stride=2),
            # Conv2d, 128 inputs, 64 outputs
            # 100x100 image size
            nn.Conv2d(128, 64, kernel_size=3, stride=1, padding=1),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=2, stride=2),
            # Conv2d, 64 inputs, 32 outputs
            # 50x50 image size
            nn.Conv2d(64, 32, kernel_size=3, stride=1, padding=1),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=2, stride=2)
        )

        self.linear_layers = nn.Sequential(
            # Linear, 32*50*50 inputs, 16 outputs
            nn.Linear(32 * 50 * 50, 16),
            # Linear, 16 inputs, 3 outputs
            nn.Linear(16, 3)
        )


    def forward(self, x):
        x = self.cnn_layers(x)
        x = x.view(x.size(0), -1)
        x = self.linear_layers(x)
        return x

如何避免此错误并在这些验证图像上训练我的图像?

  • 嗯,它看起来像 nn.Linear(32 * 50 * 50, 16) 导致这个,你需要尝试用 nn.Linear(32 * 50 * 50 * 4, 4) 替换该行
  • 现在我收到mat1 and mat2 shapes cannot be multiplied (4x460800 and 320000x4) 错误。我想我对这些形状有问题,但我不知道形状应该是什么。

标签: python csv deep-learning pytorch conv-neural-network


【解决方案1】:

答案:在您的情况下,NN 输入的形状为(3, 1280, 720),而不是您想要的(3, 200, 200)。可能您忘记修改RNetDataset 中的transform 参数。它保持None,因此不应用变换并且不调整图像大小。另一种可能性是由于以下几行而发生这种情况:

        transform = transforms.Compose([
            transforms.Resize((200, 200)), 
            transforms.ToTensor()
        ])

        if self.transform:
            image = self.transform(image)
            mask = self.transform(mask)

你有两个名为transform 的变量,但一个名为self. - 也许你把它们搞砸了。验证它,问题应该消失。

我是怎么想出来的:460800 显然是在线性层之前整形后的张量大小。根据架构,用self.cnn_layers处理的张量应该有32层,所以它的高度乘以宽度应该是460800 / 32 = 14400。假设它的高度=H,宽度=W,所以H x W = 14400。让我们了解一下,在这种情况下,原始输入大小是多少? nn.MaxPool2d(kernel_size=2, stride=2) 层将高度和宽度除以 2,它发生了 3 次。因此,原始输入大小为8H x 8W = 64 x 14400 = 936000。最后,请注意936000 = 1280 * 720。这不可能是一个神奇的巧合。结案!

另一个建议:即使您正确应用了转换,您的代码也可能无法正常工作。假设您有一个大小为 (4, 3, 200, 200) 的输入,其中 4 是批量大小。架构中的层将按如下方式处理此输入:

nn.Conv2d(3, 128, kernel_size=3, stride=1, padding=1) # -> (4, 128, 200, 200)
nn.MaxPool2d(kernel_size=2, stride=2) # -> (4, 128, 100, 100)
nn.Conv2d(128, 64, kernel_size=3, stride=1, padding=1) # -> (4, 64, 100, 100)
nn.MaxPool2d(kernel_size=2, stride=2) # -> (4, 64, 50, 50)
nn.Conv2d(64, 32, kernel_size=3, stride=1, padding=1) # -> (4, 32, 50, 50)
nn.MaxPool2d(kernel_size=2, stride=2) # -> (4, 32, 25, 25)

所以,self.linear_layers 中的第一层不应该是nn.Linear(32 * 50 * 50, 16),而是nn.Linear(32 * 25 * 25, 16)。有了这个改变,一切都应该没问题。

【讨论】:

  • 我接受了您的解决方案作为正确的解决方案。我想我在转换时遇到了你所说的错误。我修好了它。将我的第一层线性层更改为nn.Linear(32*25*25, 16)。但现在我得到UserWarning: Using a target size (torch.Size([4, 3, 200, 200])) that is different to the input size (torch.Size([4, 3])). This will likely lead to incorrect results due to broadcasting. Please ensure they have the same size. 我将损失函数更改为MSELoss
猜你喜欢
  • 2021-09-09
  • 2022-07-15
  • 2021-05-25
  • 1970-01-01
  • 2021-09-23
  • 2023-01-28
  • 2021-09-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多