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:
" File "/home/johann/Schreibtisch/NN_v0.01/classification.py", line 146, in train(epoch) File "/home/johann/Schreibtisch/NN_v0.01/classification.py", line 109, in train loss = criterion(out, target) File "/home/johann/.local/lib/python3.8/site-packages/torch/nn/modules/module.py", line 889, in _call_impl result = self.forward(*input, **kwargs) File "/home/johann/.local/lib/python3.8/site-packages/torch/nn/modules/loss.py", line 1047, in forward return F.cross_entropy(input, target, weight=self.weight, File "/home/johann/.local/lib/python3.8/site-packages/torch/nn/functional.py", line 2693, in cross_entropy return nll_loss(log_softmax(input, 1), target, weight, None, ignore_index, None, reduction) File "/home/johann/.local/lib/python3.8/site-packages/torch/nn/functional.py", 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"
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("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()```
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