RuntimeError: multi-target not supported at C:/w/b/windows/pytorch/aten/src\THCUNN/generic/ClassNLLCriterion.cu:15

username: YuhskeHujisaki
cooked: <p>Why am I getting this error? What am I doing wrong?</p>
<pre><code class="lang-auto">def perform(model, loader, optimizer):
  loss_total = 0
  accuracy_total = 0
  count = 0
  criterion = nn.CrossEntropyLoss()
  for images, labels in loader:
    images = images.cuda()
    onehot = torch.eye(4)[labels]
    onehot = torch.reshape(onehot.cuda().long().squeeze(),(1,4))
    labels = labels.cuda()
    print(onehot.shape)
    preds = model(images)
    print(preds.shape)
    loss = criterion(preds, onehot)
    
    with torch.no_grad():
      accuracy = torch.mean((torch.max(preds, dim=1)[1] == labels).float())

    if optimizer is not None:
      optimizer.zero_grad()
      loss.backward()
      optimizer.step()
    
    loss_total += float(loss.detach()) * len(images)
    accuracy_total += float(accuracy.detach()) * len(images)
    count += len(images)

  return loss_total / count, accuracy_total / count
class Dataset(dataset.Dataset):

  def __init__(self, images, labels, train=False):
    super().__init__()
    transforms = []

    if train:
      transforms.append(albumentations.HorizontalFlip(p=0.5))

    transforms.append(albumentations.ToFloat())

    self.transform = albumentations.Compose(transforms)
    self.images = images
    self.labels = labels

  def __len__(self):
    return len(self.images)

  def __getitem__(self, idx):
    image = np.rollaxis(self.transform(image=self.images[idx])['image'], 2, 0)
    label = self.labels[idx]

    return image, label

if __name__ == '__main__':
  train_labels = np.load(os.path.join("C:\\Users\\owner\\Desktop\\nihonnga\\train_data (1).npz"))['arr_1']
  train_labels = train_labels.astype('int64')
  train_images = np.load(os.path.join("C:\\Users\\owner\\Desktop\\nihonnga\\train_data (1).npz"))['arr_0']
  test_images = np.load(os.path.join("C:\\Users\\owner\\Desktop\\nihonnga\\test_data.npz"))['arr_0']
  
  model = EfficientNet.from_pretrained('efficientnet-b7')
  num_ftrs = model._fc.in_features
  model._fc = nn.Linear(num_ftrs, 4, bias=True)
  model.cuda()
  train_x, valid_x, train_y, valid_y = train_test_split(
  train_images, train_labels, test_size=0.1, random_state=421)

  train_loader = dataset.DataLoader(Dataset(train_x, train_y, train=True), batch_size=1, shuffle=True)
  valid_loader = dataset.DataLoader(Dataset(valid_x, valid_y), batch_size=1, shuffle=False)
  optimizer = optim.AdamW(model.parameters(), lr=0.001)
  log = []

  for epoch in range(100):
    model.train()

    with autograd.detect_anomaly():
      train_loss, train_accuracy = perform(model, train_loader, optimizer)

    model.eval()

    with torch.no_grad():
      valid_loss, valid_accuracy = perform(model, valid_loader, None)

    print('[{}] train(loss/accuracy)={:.2f}/{:.2f}, valid(loss/accuracy)={:.2f}/{:.2f}'.format(
      epoch + 1, train_loss, train_accuracy, valid_loss, valid_accuracy))
    
    log.append((epoch + 1, train_loss, train_accuracy, valid_loss, valid_accuracy))
  dummy_labels = np.zeros((test_images.shape[0], 1), dtype=np.int64)
  test_loader = dataset.DataLoader(
    Dataset(test_images, dummy_labels), batch_size=1, shuffle=False)

  test_labels = []
  model.eval()

  for images, _ in test_loader:
    images = images.cuda()
    
    with torch.no_grad():
      preds = model(images)
      preds = torch.max(preds, dim=1)[1]
    
    test_labels.extend(int(x) for x in preds)
  with open('C:\\Users\\owner\\Desktop\\nihonnga\\submission (4).csv', 'w') as writer:
    csv_writer = csv.writer(writer)
    csv_writer.writerow(('id', 'y'))
    csv_writer.writerows((i + 1, x) for i, x in enumerate(test_labels))
</code></pre>
<p>torch.Size([1, 4])<br>
torch.Size([1, 4])<br>
Traceback (most recent call last):<br>
File “main.py”, line 100, in <br>
train_loss, train_accuracy = perform(model, train_loader, optimizer)<br>
File “main.py”, line 39, in perform<br>
loss = criterion(preds, onehot)<br>
File “C:\Python37\lib\site-packages\torch\nn\modules\module.py”, line 1051, in _call_impl<br>
return forward_call(*input, **kwargs)<br>
File “C:\Python37\lib\site-packages\torch\nn\modules\loss.py”, line 1121, in forward<br>
ignore_index=self.ignore_index, reduction=self.reduction)<br>
File “C:\Python37\lib\site-packages\torch\nn\functional.py”, line 2824, in cross_entropy<br>
return torch._C._nn.cross_entropy_loss(input, target, weight, _Reduction.get_enum(reduction), ignore_index)<br>
RuntimeError: multi-target not supported at C:/w/b/windows/pytorch/aten/src\THCUNN/generic/ClassNLLCriterion.cu:15</p>

username: ptrblck
cooked: <p><code>nn.CrossEntropyLoss</code> expects a target tensor in the shape <code>[batch_size]</code> for a multi-class classification containing class indices in the range <code>[0, nb_classes-1]</code>.<br>
Based on your code snippet you are passing the target as one-hot encoded values, which is wrong for for <code>LongTensors</code>. In newer PyTorch versions you should be able to transform these targets to a floating point tensor and treat them as probabilities, although I would recommend to stick to the class index approach unless you really intend to use probabilities.</p>

username: YuhskeHujisaki
cooked: <p>How do I correct it?</p>

username: ptrblck
cooked: <p>Don’t one-hot encode the targets, but pass them as indices in the aforementioned shape.</p>