RuntimeError: shape '[10, 3, 150, 150]' is invalid for input of size 472500

RuntimeError: shape '[10, 3, 150, 150]' is invalid for input of size 472500

我正在尝试对 covid CT 数据集执行卷积运算,但不断出现此错误。我在 train loader 中的图像大小是 (10, 150, 150, 3),我使用 torch.reshape() 将其重塑为 [10, 3, 150, 150]。谁能帮我解决问题

我的 CNN 代码

class BConv(nn.Module):
def __init__(self, out=3):
    super(BConv, self).__init__()
    #(10, 150, 150, 3)
    self.conv1=nn.Conv2d(in_channels=3,out_channels=12,kernel_size=3,stride=1,padding=1)
    self.bn1=nn.BatchNorm2d(num_features=12)
    self.relu1=nn.ReLU()
    self.pool=nn.MaxPool2d(kernel_size=2)
    self.conv2=nn.Conv2d(in_channels=12,out_channels=20,kernel_size=3,stride=1,padding=1)
    self.relu2=nn.ReLU()
    # self.conv3=nn.Conv2d(in_channels=20,out_channels=32,kernel_size=3,stride=1,padding=1)
    # self.bn3=nn.BatchNorm2d(num_features=32)
    # self.relu3=nn.ReLU()
    self.fc=nn.Linear(in_features= 20*75*75, out_features=3)
    
def forward(self,input):
    output=self.conv1(input)
    #print("output 1", output.shape)
    output=self.bn1(output)
    #print("output 1", output.shape)
    output=self.relu1(output)
    #print("output 1", output.shape)
    output=self.pool(output)
    #print("output 1", output.shape)
    output=self.conv2(output)
    #print("output 1", output.shape)
    output=self.relu2(output)
    #print("output 1", output.shape)
    # output=self.conv3(output)
    # output=self.bn3(output)
    # output=self.relu3(output)
    print(output.shape)
        
        #Above output will be in matrix form, with shape (256,32,75,75)
    
    output=output.view(output.size(0), -1)
    
        
    output=self.fc(output)
        
    return output

数据预处理

class Ctdataset(Dataset):
    def __init__(self, path):

        self.data= pd.read_csv(path, delimiter=" ")
        data= self.data.values.tolist()
        self.image= []
        self.labels=[]
        for i in data:
            self.image.append(i[0])
            self.labels.append(i[1])

        #print(len(self.image), len(self.labels))
        #self.class_map = {"0": 0, "1":1 , "2": 2}  

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

    def __getitem__(self, idx):
        img_path = os.path.join("2A_images", self.image[idx])
        img= Image.open(img_path).convert("RGB")
        img= img.resize((150, 150))
        img= np.array(img)
        img= img.astype(float)
        return img, label
    
        

这里我考虑的是您的整个模型,包括由 conv3bn3relu3 组成的第三个块。有几点需要注意:

  • 整形与排列轴有很大不同。当您说您的输入形状为 (batch_size, 150, 150, 3) 时,这意味着通道轴在最后。由于 PyTorch 2D 内置层以 NHW 格式工作,因此您需要排列轴:您可以使用 torch.Tensor.permute:

    >>> x = torch.rand(10, 150, 150, 3)
    >>> x.permute(0, 3, 1, 2).shape
    (10, 3, 150, 150)
    
  • 假设您的输入形状为 (batch_size, 3, 150, 150),那么 relu3 的输出形状将为 (32, 75, 75)。因此,下面的全连接层必须恰好具有 32*75*75 个输入特征。

  • 但是,您需要像在代码中使用 view: output = output.view(output.size(0), -1) 一样展平此张量。另一种方法是定义一个 self.flatten = nn.Flatten() 层并用 output = self.flatten(output).

    调用它
  • 从 PyTorch v1.8.0 开始,在全连接层中设置 in_features 的替代方法是使用 nn.LazyLinear 它将根据第一个推理为您初始化它:

    >>> self.fc = nn.LazyLinear(out_features=3)
    
  • 旁注:您不需要使用 relu1relu2relu3 定义单独的 ReLU 层,因为它们是非参数函数:

    >>> self.relu = nn.ReLU()
    

完整代码供参考:

class BConv(nn.Module):
    def __init__(self, out=3):
        super().__init__()

        # input shape (10, 150, 150, 3)
        self.conv1 = nn.Conv2d(3, 12,kernel_size=3, stride=1, padding=1)
        self.bn1 = nn.BatchNorm2d(num_features=12)
        self.pool = nn.MaxPool2d(kernel_size=2)
        
        self.conv2 = nn.Conv2d(12, 20,kernel_size=3, stride=1, padding=1)

        self.conv3 = nn.Conv2d(20, 32, kernel_size=3, stride=1, padding=1)
        self.bn3 = nn.BatchNorm2d(num_features=32)
        
        self.relu = nn.ReLU()
        self.flatten = nn.Flatten()
        self.fc = nn.Linear(in_features=32*75*75, out_features=out)
    
    def forward(self,input):
        output = input.permute(0, 3, 1, 2)

        output = self.conv1(output)
        output = self.bn1(output)
        output = self.relu(output)
        output = self.pool(output)

        output = self.conv2(output)
        output = self.relu(output)

        output = self.conv3(output)
        output = self.bn3(output)
        output = self.relu(output)
        
        output = self.flatten(output)
        output = self.fc(output)
            
        return output