Nl_loss expects different targets size

Leon_Lopez: <p>I am trying to train my neuronal network. Train in the model is correct, but I can’t calculate loss. The output and the target have the same dimension.</p>
<p>I had tried to use torch.stack, but I can’t because the size of the each input is (252, x) where x is the same in the 252 elements, but is different for the others inputs.</p>
<p>I use a custom Dataset:</p>
<pre><code class="lang-auto">class MusicDataSet(Dataset):
def __init__(self, transform=None):
    self.ms, self.target, self.tam = sd.cargarDatos()  
    self.mean, self.std = self.NormalizationValues()                    
def __len__(self):
    return self.tam

def __getitem__(self, idx):
    #Normalize
    inp = (self.ms[idx]-self.mean)/self.std
    inp = torch.from_numpy(inp).float()    
    inp = inp.t()
    inp = inp.to('cuda')

    target= torch.from_numpy(self.target[idx])
    target = target.long()
    target = target.t()
    target = target.to('cuda')

    return inp, target
</code></pre>
<p>I must say that list can’t be cast with something like: target = torch.Tensor() or torch.stack() because this (252, x), as I have already said.</p>
<pre><code class="lang-auto">def music_collate_fn(batch):
    data = [item[0] for item in batch]
    data = pad_sequence(data, batch_first=True)
    target = [item[0] for item in batch]
    target = pad_sequence(target, batch_first=True)
    return data, target


musicSet = mds.MusicDataSet()
train_loader = torch.utils.data.DataLoader(musicSet,batch_size=50, collate_fn = music_collate_fn, shuffle=False)

input_dim = 252
hidden_dim = (512,1024,512)
output_dim = 88
mlp = rn.MLP(input_dim, hidden_dim, output_dim).to(device)

optimizer = torch.optim.RMSprop(mlp.parameters(), lr = learning_rate)
criterion = nn.CrossEntropyLoss()
for batch_idx, (x,y) in enumerate(train_loader):
    outputs = mlp(x.to(device))
    loss = criterion(outputs, y)
    optimizer.zero_grad()           
    loss.backward()                 
    optimizer.step()
</code></pre>
<p>The size of output and target is the same:</p>
<pre><code class="lang-auto">output: torch.Size([50, 288, 88])
target:  torch.Size([50, 288, 88])
</code></pre>
<p>But the next error apears when I try to calculate loss:</p>
<pre><code class="lang-auto"> File "&lt;ipython-input-205-3c47d7aa11a4&gt;", line 32, in &lt;module&gt;
    loss = criterion(outputs, y)

  File "C:\ProgramData\Anaconda3\lib\site-packages\torch\nn\modules\module.py", line 489, in __call__
    result = self.forward(*input, **kwargs)

  File "C:\ProgramData\Anaconda3\lib\site-packages\torch\nn\modules\loss.py", line 904, in forward
    ignore_index=self.ignore_index, reduction=self.reduction)

  File "C:\ProgramData\Anaconda3\lib\site-packages\torch\nn\functional.py", line 1970, in cross_entropy
    return nll_loss(log_softmax(input, 1), target, weight, None, ignore_index, None, reduction)

  File "C:\ProgramData\Anaconda3\lib\site-packages\torch
\nn\functional.py", line 1800, in nll_loss
    out_size, target.size()))

ValueError: Expected target size (50, 88), got torch.Size([50, 288, 88])
</code></pre>

ptrblck: <p><code>nn.NLLLoss</code> is used for a multi-class classification use case.<br>
While the model output should contain the log probabilities for all classes, the target should be a <code>LongTensor</code> containing the class indices.<br>
Based on the shape it looks like your target might be a one-hot encoded tensor.<br>
If that’s the case (and the number of classes is encoded in dim1), you could use</p>
<pre><code class="lang-python">target = torch.argmax(target, 1)
</code></pre>
<p>to get the class indices in the right shape.</p>

Leon_Lopez: <p>My target is not encoded.</p>
<p>I am trying to classify isolated musical notes(88 exactly). Each note has input of 252 tensors, and each tensor has a variable size. That is way I can’t use the default collate_fn. You can see in <strong>getitem</strong>() function target is convert to LongTensor.</p>
<p>The target of each note is a tensor. If we have the note 0, tensor number 0 is filled with 1 and the rest of tensors are filled with 0.  Target for note 0:</p>
<p>tensor([[1., 0., 0.,  …, 0., 0., 0.],<br>
[1., 0., 0.,  …, 0., 0., 0.],<br>
[1., 0., 0.,  …, 0., 0., 0.],<br>
…,<br>
[1., 0., 0.,  …, 0., 0., 0.],<br>
[1., 0., 0.,  …, 0., 0., 0.],<br>
[1., 0., 0.,  …, 0., 0., 0.]])</p>
<p>Thanks so much!</p>

ptrblck: <p>Thanks for the information!<br>
Based on the description, I assume the output of <code>[50, 288, 88]</code> corresponds to <code>[batch_size, seq_length, nb_classes]</code>. Is this correct?</p>
<p>If so, the class dimension should be in dim1: <code>[batch_size, nb_classes, seq_length]</code>.<br>
Also, it does look as if your target is one-hot encoded, if you are setting a 1 for the active class.<br>
If that’s the case, permute the target like the output (<code>target = target.permute(0, 2, 1)</code>) and use <code>torch.argmax(target, 1)</code> to get the class index.</p>

Elahe_Heydari: <p>Hi <a class="mention" href="/u/ptrblck">@ptrblck</a><br>
I have a question about  loss. CrossEntropyLoss gives loss of all of classes, but I want to get loss of class 1 ,how can I get loss of each class?</p>
<pre><code class="lang-auto">N, C = 5, 4
loss = nn.CrossEntropyLoss()
data = torch.randn(N, 16, 10, 10)
conv = nn.Conv2d(16, C, (3, 3))
target = torch.empty(N, 8, 8, dtype=torch.long).random_(0, C)
pr=conv(data)
output = loss(pr, target)
output.backward()
</code></pre>

ptrblck: <p>Would using <code>nn.CrossEntropyLoss(reduction='none')</code> work for you?<br>
This will return the unreduced loss and you could then print or process the row corresponding to your desired label.</p>

Elahe_Heydari: <p>It works without loss.backward()  and the shape of output for following code is (8,64,64,64), but I can’t get loss of each class.</p>
<pre><code class="lang-auto">import torch
N, C = 8, 21
loss = torch.nn.CrossEntropyLoss(reduction='none')
data = torch.randn(8,21 ,64, 64, 64)
target = torch.empty(8, 64, 64,64, dtype=torch.long).random_(0, 21)
# target.requires_grad = True
output = loss(data, target)
# output.backward()
print(output.shape)
### torch.Size([8, 64, 64, 64])

</code></pre>

ptrblck: <p>You could create masks based on the <code>target</code> and index the loss with it to get the losses for all classes in the current batch.</p>

Elahe_Heydari: <p>Thanks for reply.<br>
I write this code ,is it correct?<br>
I have another question, if i use some losses in my code, is it necessary to use loss.backward() for each of losses?</p>
<pre><code class="lang-auto">import torch
N, C = 8, 21
loss = torch.nn.MSELoss()
data = torch.randn(8,21 ,64, 64, 64)
target = torch.empty(8, 64, 64,64, dtype=torch.long).random_(0, 21)

_, preds_argmax = torch.max(data.data, 1)
labels3 = target.eq(3).float()
preds3 = preds_argmax.eq(3).float()
loss1 = loss(preds3, labels3)
# loss for class 3
print(loss1)


</code></pre>

ptrblck: <p>This code will most likely not work as intended, since you are passing the prediction indices after <code>torch.max</code> to the criterion, which will break the computation graph.<br>
Also, don’t use the <code>.data</code> attribute.</p>
<p>Could you please give me an example, what the loss of a particular class would look like?<br>
Do you want to get the predictions of your model for class 3 and compare it as a binary classification?</p>

Elahe_Heydari: <p>I use CrossEntropy for calculating loss of 21 classes.(my first post in this topic).<br>
But in my project , I must calculate loss of each class(for example class 1).<br>
And for it,I use MSEloss for it.<br>
I extract the parameters of class 1 in preds and target,then I used binary loss for it.<br>
<a href="https://discuss.pytorch.org/t/loss-and-accuracy-for-each-class-in-segmentation/74707">this post</a> shows my project better.</p>