【问题标题】:PyTorch Error while building CNN: "1only batches of spatial targets supported (3D tensors) but got targets of size: : [1, 2, 64, 64]"构建 CNN 时出现 PyTorch 错误:“仅支持 1 批空间目标(3D 张量),但目标大小为:: [1, 2, 64, 64]”
【发布时间】:2021-09-07 07:38:31
【问题描述】:

我想构建一个类似于本文中的 CNN:https://arxiv.org/abs/1603.08511 (https://richzhang.github.io/colorization/)。 作为数据,我从 LAB - 颜色空间获得了图像。我为这些 l 和 a、b 值编写了一个数据加载器,并将 l 值作为我的神经网络的输入,并将 a、b 值作为标签。 我在标准损失函数中收到错误“仅支持一批空间目标(3D 张量),但目标大小为:: [1, 2, 64, 64]”。 我将作为“标签”插入到标准()方法中的内容存在问题。但是标签的尺寸对我来说似乎是正确的:[1, 2, 64, 64] --> [batch_size, in_channels (a,b), width, heigth]。 我将 batch_size 设置为 1 以查看它是否正常工作。我尝试使用 pytorch.squeeze() 仅削减 batch_size 维度,但它没有用。我不明白为什么我不能将这种形状和大小的向量放入标准()函数。任何帮助表示赞赏!我的代码如下:

#importing the libraries
import numpy as np
import pandas as pd

from numpy import random
# for creating validation set
from sklearn.model_selection import train_test_split

# PyTorch libraries and modules
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from torch.autograd import Variable
from torch.nn import Linear, ReLU, CrossEntropyLoss, Sequential, Conv2d, MaxPool2d, Module, Softmax, BatchNorm2d, Dropout
from torch.optim import Adam, SGD
from torch.utils.data import Dataset, DataLoader
from torchvision import datasets
from torch.utils.data.sampler import SubsetRandomSampler

from typing import Any, Tuple


# set device
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

# define local paths
L_path = 'l/gray_scale.npy'
ab1_path = 'ab/ab/ab1.npy'
ab2_path = 'ab/ab/ab2.npy'
ab3_path = 'ab/ab/ab3.npy'

image_size = 64


class ColorDataset(Dataset):
    def __init__(self, transformations=None, seed=42) -> None:
        if transformations is None:
            self.transformations = transforms.Compose([
                transforms.ToPILImage(),
                transforms.Resize(image_size),
                transforms.ToTensor()
            ])
        else:
            self.transformations = transformations
        self.seed = seed
        self.L = np.load(L_path)
        self.L = np.expand_dims(self.L, -1)
        # self.L = self.L.transpose((0, 3, 1, 2))
        self.ab = np.concatenate([
            np.load(ab1_path),
            np.load(ab2_path),
            np.load(ab3_path)
        ], axis=0)
        # self.ab = self.ab.transpose((0, 3, 1, 2))
        print("All inputs loaded")

    def __len__(self) -> int:
        return len(self.L)

    def __getitem__(self, index: int) -> Tuple[Any, Any]:
        random.seed(self.seed)
        L = self.transformations(self.L[index])
        random.seed(self.seed)
        ab = self.transformations(self.ab[index])
        return L, ab


# initialize dataset
dataset = ColorDataset()
dataset_size = len(dataset)

# set relative test size (for split)
test_size = 0.3

indices = list(range(dataset_size))
np.random.shuffle(indices)
split = int(np.floor(test_size * dataset_size))
train_index, test_index = indices[split:], indices[:split]

train_sampler = SubsetRandomSampler(train_index)
test_sampler = SubsetRandomSampler(test_index)

# set batch size
batch_size = 1

train_loader = DataLoader(dataset, batch_size=batch_size, sampler=train_sampler, num_workers=0)
test_loader = DataLoader(dataset, batch_size=batch_size, sampler=test_sampler, num_workers=0)


# Network
class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.conv1_1 = nn.Conv2d(1, 64, 1)
        self.conv1_2 = nn.Conv2d(64, 64, 1)
        self.batch_norm_1 = nn.BatchNorm2d(64) 
        self.conv2_1 = nn.Conv2d(64, 128, 1, 2)
        self.conv2_2 = nn.Conv2d(128, 128, 1)
        self.batch_norm_2 = nn.BatchNorm2d(128) 
        self.conv3_1 = nn.Conv2d(128, 256, 1, 2)
        self.conv3_2 = nn.Conv2d(256, 256, 1)
        self.conv3_3 = nn.Conv2d(256, 256, 1)
        self.batch_norm_3 = nn.BatchNorm2d(256)
        self.conv4_1 = nn.Conv2d(256, 512, 1, 2)
        self.conv4_2 = nn.Conv2d(512, 512, 1)
        self.conv4_3 = nn.Conv2d(512, 512, 1)
        self.batch_norm_4 = nn.BatchNorm2d(512)
        self.conv5_1 = nn.Conv2d(512, 512, 1)
        self.conv5_2 = nn.Conv2d(512, 512, 1)
        self.conv5_3 = nn.Conv2d(512, 512, 1)
        self.batch_norm_5 = nn.BatchNorm2d(512)
        self.conv6_1 = nn.Conv2d(512, 512, 1)
        self.conv6_2 = nn.Conv2d(512, 512, 1)
        self.conv6_3 = nn.Conv2d(512, 512, 1)
        self.batch_norm_6 = nn.BatchNorm2d(512)
        self.conv7_1 = nn.Conv2d(512, 256, 1)
        self.conv7_2 = nn.Conv2d(256, 256, 1)
        self.conv7_3 = nn.Conv2d(256, 256, 1)
        self.batch_norm_7 = nn.BatchNorm2d(256)
        self.conv8_1 = nn.Conv2d(256, 128, 1)
        self.conv8_2 = nn.Conv2d(128, 128, 1, 1) 
        self.conv8_3 = nn.Conv2d(128, 128, 1)

        
        #define forward pass
    def forward(self, x):
        # Pass data through conv1_1
        x = self.conv1_1(x)
        # Use the rectified-linear activation function over x
        x = F.relu(x)
        x = self.conv1_2(x)
        x = F.relu(x)
        #batch normalization
        x = self.batch_norm_1(x)
        x = self.conv2_1(x)
        x = F.relu(x)
        x = self.conv2_2(x)
        x = F.relu(x)
        #batch normalization
        x = self.batch_norm_2(x)
        x = self.conv3_1(x)
        x = F.relu(x)
        x = self.conv3_2(x)
        x = F.relu(x)
        x = self.conv3_3(x)
        #batch normalization
        x = self.batch_norm_3(x)
        x = self.conv4_1(x)
        x = F.relu(x)
        x = self.conv4_2(x)
        x = F.relu(x)
        x = self.conv4_3(x)
        #batch normalization
        x = self.batch_norm_4(x)
        x = self.conv5_1(x)
        x = F.relu(x)
        x = self.conv5_2(x)
        x = F.relu(x)
        x = self.conv5_3(x)
        #batch normalization
        x = self.batch_norm_5(x)
        x = self.conv6_1(x)
        x = F.relu(x)
        x = self.conv6_2(x)
        x = F.relu(x)
        x = self.conv6_3(x)
        #batch normalization
        x = self.batch_norm_6(x)
        x = self.conv7_1(x)
        x = F.relu(x)
        x = self.conv7_2(x)
        x = F.relu(x)
        x = self.conv7_3(x)
        #batch normalization
        x = self.batch_norm_7(x)
        x = self.conv8_1(x)
        x = F.relu(x)
        x = self.conv8_2(x)
        x = F.relu(x)
        x = self.conv8_3(x)
        return x
    
    
model = Net()
optimizer = Adam(model.parameters(), lr=0.07)
# defining the loss function
criterion = CrossEntropyLoss()

# checking if GPU is available
if torch.cuda.is_available():
    model = model.cuda()
    criterion = criterion.cuda()
    #labels und output des netzwerks in criterion
      
    
def train(epoch):
    model.train()
    train_loss = 0
    
    # train the model
    model.train() # prep model for training
    for data, label in train_loader:
        data = data.to('cuda')
        label = label.to('cuda')
        print(label.size())
        # clear the gradients of all optimized variables
        optimizer.zero_grad()
        #forward pass: compute predicted outputs by passing inputs to the model
        output = model(data)
        # calculate the loss
    
        label = label.long() #convert label to long since in criterion long is expected
        loss = criterion(output, label) #l value is data, ab values are labels
        # backward pass: compute gradient of the loss with respect to model parameters
        loss.backward()
        # perform a single optimization step (parameter update)
        optimizer.step()
        # update running training loss
        train_loss += loss.item() * data.size(0)
    
    
    # calculate average loss over an epoch
    train_loss = train_loss / len(train_loader.sampler)
   
    # printing the loss
    print('Epoch : ', epoch+1, '\t', 'loss :', train_loss)
        
    
# defining number of epochs 
n_epochs = 1

# empty list to store training losses (actually not used)
train_losses = []

# training the model
for epoch in range(n_epochs):
    train(epoch)

这里是错误:

---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
<ipython-input-25-c26ffccd8f7e> in <module>
    250 # training the model
    251 for epoch in range(n_epochs):
--> 252     train(epoch)

<ipython-input-25-c26ffccd8f7e> in train(epoch)
    224         label = label.long() #convert label to long since in criterion long is expected
    225         print(label.size())
--> 226         loss = criterion(output, label) #l value is data, ab values are labels
    227         # backward pass: compute gradient of the loss with respect to model parameters
    228         loss.backward()

~\anaconda3\lib\site-packages\torch\nn\modules\module.py in _call_impl(self, *input, **kwargs)
    725             result = self._slow_forward(*input, **kwargs)
    726         else:
--> 727             result = self.forward(*input, **kwargs)
    728         for hook in itertools.chain(
    729                 _global_forward_hooks.values(),

~\anaconda3\lib\site-packages\torch\nn\modules\loss.py in forward(self, input, target)
    960     def forward(self, input: Tensor, target: Tensor) -> Tensor:
    961         return F.cross_entropy(input, target, weight=self.weight,
--> 962                                ignore_index=self.ignore_index, reduction=self.reduction)
    963 
    964 

~\anaconda3\lib\site-packages\torch\nn\functional.py in cross_entropy(input, target, weight, size_average, ignore_index, reduce, reduction)
   2466     if size_average is not None or reduce is not None:
   2467         reduction = _Reduction.legacy_get_string(size_average, reduce)
-> 2468     return nll_loss(log_softmax(input, 1), target, weight, None, ignore_index, None, reduction)
   2469 
   2470 

~\anaconda3\lib\site-packages\torch\nn\functional.py in nll_loss(input, target, weight, size_average, ignore_index, reduce, reduction)
   2264         ret = torch._C._nn.nll_loss(input, target, weight, _Reduction.get_enum(reduction), ignore_index)
   2265     elif dim == 4:
-> 2266         ret = torch._C._nn.nll_loss2d(input, target, weight, _Reduction.get_enum(reduction), ignore_index)
   2267     else:
   2268         # dim == 3 or dim > 4

RuntimeError: 1only batches of spatial targets supported (3D tensors) but got targets of size: : [1, 2, 64, 64]

【问题讨论】:

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


    【解决方案1】:

    您为什么使用CrossEntropyLoss() 来完成这项任务?
    为什么你的网络输出 128dim 的“像素”?
    您的预测与目标的空间维度是什么?
    您仅使用 1x1 内核,这意味着您的模型对其邻居的每个像素独立进行预测。您希望它如何学习预测有意义的着色?

    您应该回到绘图台,重新考虑您的模型和标准。现在这个错误是你最不必担心的。

    【讨论】:

    • 1.在原始网络中,他们也使用了 CrossEntropyLoss,所以我也是这样做的,至少他们提到在最后一层(conv8_3)之后,他们强加了一个 1x1 卷积层和一个“交叉熵损失层”。所以我猜我也可以使用这个损失函数。 2. 输出中的错误为真。我在 conv8_3 层 tue 返回具有 2 个通道的输出之后添加了这一行“self.conv_1x1 = nn.Conv2d(128,2, 1)”。这是因为我想为每个输入“L”值返回两个“a,b”值。
    • @Janosch 他们在什么任务中使用了交叉熵损失?
    • 他们将其用于多模态分类任务。他们量化输入对应 a、b 值的 (l) 值,并使用 CrossEntropyLoss 对结果进行分类。但是谢谢,我刚刚将我的损失函数切换到 BCEWithLogitsLoss() 函数,现在我的代码在没有抛出错误的情况下被执行......我仍然需要检查结果,但没有错误地运行是一个很好的第一步!
    猜你喜欢
    • 2021-07-31
    • 1970-01-01
    • 1970-01-01
    • 2019-07-22
    • 2021-09-13
    • 1970-01-01
    • 1970-01-01
    • 2021-05-10
    • 2020-04-26
    相关资源
    最近更新 更多