pytorch - 灰度图像分类模型上的输入和模型大小错误错误

问题描述 投票:0回答:1

我有 (650, 650) 个带标签的灰度图像,并尝试构建 pytorch CNN 模型。

我认为快完成了,但低于错误。

RuntimeError: Given groups=1, weight of size [32, 1, 3, 3], expected input[1, 32, 650, 650] to have 1 channels, but got 32 channels instead 

我的整个代码如下。

import numpy as np
import pandas as pd
import torch
import torchvision
from torchvision import transforms
from torchvision.datasets import ImageFolder
from sklearn.model_selection import train_test_split
from torch.utils.data import DataLoader, TensorDataset
import torch.nn.functional as F
import torch.nn as nn
df = pd.DataFrame({"Img" : [np.random.randint(0, 255, size=(650, 650))], "label":[[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]}) # this is pseudo data. only shape and type is same. 
df.Img=df.Img.apply(lambda x: x.astype(np.single))
X_train, X_test, y_train, y_test = train_test_split(df, df.label, test_size=0.2, random_state=1)

X_train, X_val, y_train, y_val = train_test_split(X_train, y_train, test_size=0.25, random_state=1)
X = torch.tensor(X_train['Img'].tolist(), dtype=torch.float32)
y = torch.tensor(X_train['label'].tolist())
dataset = TensorDataset(X, y)
val_dataset = TensorDataset(torch.tensor(X_val['F_Img'].tolist()), torch.tensor(X_val['label'].tolist()))
batch_size=32

dataloader = DataLoader(dataset, batch_size=batch_size, shuffle=True)
val_dataloader = DataLoader(val_dataset, batch_size=batch_size, shuffle=False)

train_dl = dataloader
val_dl = val_dataloader

class ImageClassificationBase(nn.Module):
    
    def training_step(self, batch):
        images, labels = batch 
        out = self(images)                  # Generate predictions
        loss = F.cross_entropy(out, labels) # Calculate loss
        return loss
    
    def validation_step(self, batch):
        images, labels = batch 
        out = self(images)                    # Generate predictions
        loss = F.cross_entropy(out, labels)   # Calculate loss
        acc = accuracy(out, labels)           # Calculate accuracy
        return {'val_loss': loss.detach(), 'val_acc': acc}
        
    def validation_epoch_end(self, outputs):
        batch_losses = [x['val_loss'] for x in outputs]
        epoch_loss = torch.stack(batch_losses).mean()   # Combine losses
        batch_accs = [x['val_acc'] for x in outputs]
        epoch_acc = torch.stack(batch_accs).mean()      # Combine accuracies
        return {'val_loss': epoch_loss.item(), 'val_acc': epoch_acc.item()}
    
    def epoch_end(self, epoch, result):
        print("Epoch [{}], train_loss: {:.4f}, val_loss: {:.4f}, val_acc: {:.4f}".format(
            epoch, result['train_loss'], result['val_loss'], result['val_acc']))

class Net(ImageClassificationBase):
    def __init__(self):
        super().__init__()
        self.network = nn.Sequential(
            
            nn.Conv2d(in_channels=1, out_channels=32, kernel_size = 3, padding = 1),
            nn.ReLU(),
            nn.Conv2d(32,64, kernel_size = 3, stride = 1, padding = 1),
            nn.ReLU(),
            nn.MaxPool2d(2,2),
        
            nn.Conv2d(64, 128, kernel_size = 3, stride = 1, padding = 1),
            nn.ReLU(),
            nn.Conv2d(128 ,128, kernel_size = 3, stride = 1, padding = 1),
            nn.ReLU(),
            nn.MaxPool2d(2,2),
            
            nn.Conv2d(128, 256, kernel_size = 3, stride = 1, padding = 1),
            nn.ReLU(),
            nn.Conv2d(256,256, kernel_size = 3, stride = 1, padding = 1),
            nn.ReLU(),
            nn.MaxPool2d(2,2),
            
            nn.Flatten(),
            nn.Linear(6561,1024),
            nn.ReLU(),
            nn.Linear(1024, 512),
            nn.ReLU(),
            nn.Dropout(p=0.5),
            nn.Linear(512,13)
        )
    
    def forward(self, xb):
        return self.network(xb)
def accuracy(outputs, labels):
    _, preds = torch.max(outputs, dim=1)
    return torch.tensor(torch.sum(preds == labels).item() / len(preds))

  
@torch.no_grad()
def evaluate(model, val_loader):
    model.eval()
    outputs = [model.validation_step(batch) for batch in val_loader]
    return model.validation_epoch_end(outputs)

  
def fit(epochs, lr, model, train_loader, val_loader, opt_func = torch.optim.SGD):
    
    history = []
    optimizer = opt_func(model.parameters(),lr)
    for epoch in range(epochs):
        
        model.train()
        train_losses = []
        for batch in train_loader:
            loss = model.training_step(batch)
            train_losses.append(loss)
            loss.backward()
            optimizer.step()
            optimizer.zero_grad()
            
        result = evaluate(model, val_loader)
        result['train_loss'] = torch.stack(train_losses).mean().item()
        model.epoch_end(epoch, result)
        history.append(result)
    
    return history
num_epochs = 30
opt_func = torch.optim.Adam
lr = 0.001
#fitting the model on training data and record the result after each epoch
device = 'cuda' if torch.cuda.is_available() else 'cpu'
model = Net().to(device)
model
history = fit(num_epochs, lr, model, train_dl, val_dl, opt_func)
# RuntimeError: Given groups=1, weight of size [32, 1, 3, 3], expected input[1, 32, 650, 650] to have 1 channels, but got 32 channels instead

我用谷歌搜索了一下,发现了一些类似的问题

运行时错误:给定组=1,权重大小为[64,32,3,3],预期输入[128,64,32,32]有32个通道,但得到了64个通道

点是模型中的形状匹配,但即使我知道,我也找不到问题出在哪里。我感到羞耻......

pytorch
1个回答
0
投票

您的模型期望输入的形状为

(bs, ch, h, w)
,在本例中为
(32, 1, 650, 650)
。您的实际输入的形状为
(1, 32, 650, 650)

发生这种情况的原因是您的图像具有形状

(650, 650)
。数据加载器将它们堆叠到
(bs, 650, 650)
nn.Conv2d
需要四个暗淡的输入,因此它添加了一个单位轴,将输入转换为
(1, bs, 650, 650)

解决方案是在图像中添加单位轴:

np.random.randint(0, 255, size=(1, 650, 650))

这将导致您的数据加载器输出具有形状

(bs, 1, 650, 650)

© www.soinside.com 2019 - 2024. All rights reserved.