Pytorch error: RuntimeError: 1D target tensor expected, multi-target not supported

Pytorch error: RuntimeError: 1D target tensor expected, multi-target not supported

我目前正在研究一个神经元网络,它可以对猫和狗以及除猫狗以外的所有事物进行分类。我的程序有这个:我无法解决的错误:

”文件“/home/johann/Schreibtisch/NN_v0.01/classification.py”,第 146 行,在 火车(纪元) 文件“/home/johann/Schreibtisch/NN_v0.01/classification.py”,第 109 行,在 train 中 损失=标准(出局,目标) 文件“/home/johann/.local/lib/python3.8/site-packages/torch/nn/modules/module.py”,第 889 行,在 _call_impl 结果 = self.forward(*输入, **kwargs) 文件“/home/johann/.local/lib/python3.8/site-packages/torch/nn/modules/loss.py”,第 1047 行,向前 return F.cross_entropy(输入、目标、权重=self.weight, 文件“/home/johann/.local/lib/python3.8/site-packages/torch/nn/functional.py”,第 2693 行,在 cross_entropy return nll_loss(log_softmax(input, 1), target, weight, None, ignore_index, None, reduction) 文件“/home/johann/.local/lib/python3.8/site-packages/torch/nn/functional.py”,第 2388 行,在 nll_loss 中 ret = torch._C._nn.nll_loss(输入,目标,权重,_Reduction.get_enum(减少),ignore_index) RuntimeError:预期为 1D 目标张量,不支持多目标

代码:

import os
from torchvision import transforms
from PIL import Image
from os import listdir
import random
import torch.optim as optim
from torch.autograd import Variable
import torch.nn.functional as F
import torch.nn as nn
import matplotlib.pyplot as plt
from tqdm import tqdm

normalize = transforms.Normalize(
    mean = [0.485, 0.456, 0.406],
    std = [0.229, 0.224, 0.225])

transform = transforms.Compose([
     transforms.Resize(256),
     transforms.CenterCrop(256),
     transforms.ToTensor(), normalize])

train_data_list = []
target_list = []
train_data = []
waited = False
files = listdir('catsanddogs/train/')
for i in range(len(listdir('catsanddogs/train/'))):
    if len(train_data) == 58 and not waited:
        waited = True
        continue
    f = random.choice(files)
    files.remove(f)
    img = Image.open("catsanddogs/train/" + f)
    img_tensor = transform(img)
    train_data_list.append(img_tensor)
    isSomething = 0
    isCat = 1 if 'cat' in f else 0
    isDog = 1 if 'dog' in f else 0
    if isDog == 0 and isCat == 0:
        isSomething = 1
    target = [isCat, isDog, isSomething] #, isSomthing
    target_list.append(target)
    if len(train_data_list) >= 256:
        train_data.append((torch.stack(train_data_list), target_list))
        train_data_list = []
        target_list = []
        print('Loaded batch ', len(train_data), 'of ', int(len(listdir('catsanddogs/train/')) / 64))
        print('Percentage Done: ', 100 * len(train_data) / int(len(listdir('catsanddogs/train/')) / 64), '%')
        if len(train_data) > 2:
            break

class Netz(nn.Module):
    def __init__(self):
        super(Netz, self).__init__()
        self.conv1 = nn.Conv2d(3, 6, kernel_size=(5, 5))
        self.conv2 = nn.Conv2d(6, 12, kernel_size=(5, 5))
        self.conv3 = nn.Conv2d(12, 18, kernel_size=(5, 5))
        self.conv4 = nn.Conv2d(18, 24, kernel_size=(5, 5))
        self.fc1 = nn.Linear(3456, 1000)
        self.fc2 = nn.Linear(1000, 3)

    def forward(self, x):
       x = self.conv1(x)
       x = F.max_pool2d(x, 2)
       x = F.relu(x)
       x = self.conv2(x)
       x = F.max_pool2d(x, 2)
       x = F.relu(x)
       x = self.conv3(x)
       x = F.max_pool2d(x, 2)
       x = F.relu(x)
       x = self.conv4(x)
       x = F.max_pool2d(x, 2)
       x = F.relu(x)
       x = x.view(-1, 3456)
       x = F.relu(self.fc1(x))
       x = self.fc2(x)
       return F.softmax(x, dim=1)

model = Netz()
#if os.path.isfile('catdognetz.pt'):
    #model = torch.load('catdognetz.pt')

optimizer = optim.SGD(model.parameters(), lr=0.001, momentum=0.9)

def count_parameters(model):
  return sum(p.numel() for p in model.parameters() if p.requires_grad)

count_parameters(model)

train_losses = []
train_accu = []


def train(epoch):
    print('\nEpoch : %d' % epoch)
    model.train()
    running_loss = 0
    correct = 0
    total = 0
    for data, target in tqdm(train_data):
        target = torch.Tensor(target)
        data = Variable(data)
        target = Variable(target)
        optimizer.zero_grad()
        out = model(data)
        criterion = nn.CrossEntropyLoss()
        loss = criterion(out, target)
        loss.backward()
        optimizer.step()

        running_loss += loss.item()
        predicted = out.max(1)
        total += target.size(0)
        correct += predicted.eq(target).sum().item()

    train_loss = running_loss / len(train_data)
    accu = 100. * float(correct) / total

    train_accu.append(accu)
    train_losses.append(train_loss)
    print('Train Loss: %.3f | Accuracy: %.3f' % (train_loss, accu))

def test():
    model.eval()
    file = listdir('catsanddogs/test/')
    f = random.choice(file)
    img = Image.open('catsanddogs/test/' + f)
    img_eval_tensor = transform(img)
    img_eval_tensor.unsqueeze_(0)
    data = Variable(img_eval_tensor)
    out = model(data)
    what = "It's a cat"
    print(out.data.max(1, keepdim=True)[1].cpu().numpy()[0])
    if out.data.max(1, keepdim=True)[1].cpu().numpy()[0] != 0:
        what = "It's a Dog"
    if out.data.max(1, keepdim=True)[1].cpu().numpy()[0] != 0 and out.data.max(1, keepdim=True)[1].cpu().numpy()[0] != 1:
        what = "Neither"
    print(what)
    img.show()
    #x = input('')

epochs = 10
for epoch in range(1, epochs + 1):
    train(epoch)
    #test()
    torch.save(model, 'catdognetz.pt')

plt.plot(train_accu,'-o')
plt.xlabel('epoch')
plt.ylabel('accuracy')
plt.legend(['Kurve: Training'])
plt.title('Train Accuracy')

plt.show()

plt.plot(train_losses,'-o')
plt.xlabel('epoch')
plt.ylabel('loss bzw. Verlust')
plt.legend(['Kruve : Training'])
plt.title('Train Loss')

plt.show()```

此错误背后的原因是您的目标列表是这样的列表列表:

   target =  [[1,0,0],[0,1,0],[0,0,1],...]

您应该使用一维张量而不是 one-hot 代码列表,因为 CrossEntropyLoss 不接受 one-hot 编码张量。例如,您可以使用:

target = torch.tensor([0, 1, 2, 2, 1, 0, 0, ...])    # cat = 1, dog=2, something else= 2

您可以通过以下方式自动将目标从 one-hot 编码列表转换为 类 张量:

target = torch.tensor(target)
target= torch.argmax(target ,axis=1)

或者您可以更改算法以创建一维张量而不是列表列表。

你可以阅读更多CrossEntropyLoss的文档here