Pytorch error: RuntimeError: 1D target tensor expected, multi-target not supported
I am currently working on an neuronal network that can classify cats and dog and everything thats not cat nor dog. And my programm has this: error i can't solve:
&quot; File &quot;/home/johann/Schreibtisch/NN_v0.01/classification.py&quot;, line 146, in 
train(epoch)
File &quot;/home/johann/Schreibtisch/NN_v0.01/classification.py&quot;, line 109, in train
loss = criterion(out, target)
File &quot;/home/johann/.local/lib/python3.8/site-packages/torch/nn/modules/module.py&quot;, line 889, in _call_impl
result = self.forward(*input, **kwargs)
File &quot;/home/johann/.local/lib/python3.8/site-packages/torch/nn/modules/loss.py&quot;, line 1047, in forward
return F.cross_entropy(input, target, weight=self.weight,
File &quot;/home/johann/.local/lib/python3.8/site-packages/torch/nn/functional.py&quot;, line 2693, in cross_entropy
return nll_loss(log_softmax(input, 1), target, weight, None, ignore_index, None, reduction)
File &quot;/home/johann/.local/lib/python3.8/site-packages/torch/nn/functional.py&quot;, line 2388, in nll_loss
ret = torch._C._nn.nll_loss(input, target, weight, _Reduction.get_enum(reduction), ignore_index)
RuntimeError: 1D target tensor expected, multi-target not supported&quot;
The code:
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(&quot;catsanddogs/train/&quot; + 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) &gt;= 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) &gt; 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 = &quot;It's a cat&quot;
    print(out.data.max(1, keepdim=True)[1].cpu().numpy()[0])
    if out.data.max(1, keepdim=True)[1].cpu().numpy()[0] != 0:
        what = &quot;It's a Dog&quot;
    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 = &quot;Neither&quot;
    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()```


The reason behind this error is that your targets list are list of lists like that:
   target =  [[1,0,0],[0,1,0],[0,0,1],...]

You should use an 1D tensor instead of the one-hot code list because CrossEntropyLoss does not accept one-hot coded tensor. For example, you can use this:
target = torch.tensor([0, 1, 2, 2, 1, 0, 0, ...])    # cat = 1, dog=2, something else= 2

You can automatically convert your targets from a one-hot coded list to a tensor of classes by:
target = torch.tensor(target)
target= torch.argmax(target ,axis=1)

Or you can change your algorithm to create a 1D tensor instead of a list of lists.
You can read more the documentation of CrossEntropyLoss here
