How to compute cross entropy loss for classification in tensor

isalirezag: <p>I have N classes and my output of the convolution is in shape of<br>
BxNxDxD, where B is the batch size, N is the number of classes, and D is the dimension of the out put.<br>
I am trying re-implement ssd object detection.</p>
<p>so basically if i call my output Out, Out[0,:,0,0] is the classification results for position (0,0),<br>
I made my GT to be in the same shape as Out, and i send Out to the  <code>Out = nn.Softmax2d(Out)</code> , but i dont know how should i use the GT and Out for computing cross entropy loss at the end.</p>

ptrblck: <p>Your target should have the dimensions <code>[batch_size, height, width]</code> filled with the corresponding class indices.<br>
The <a href="https://pytorch.org/docs/stable/nn.html#torch.nn.CrossEntropyLoss">docs</a> on <code>nn.CrossEntropyLoss</code> give you an example.</p>

chenglu: <p>Just flatten everything in one order, let’s say your final feature map is 7 x 7, batch size is 4, class number is 80. Then the output tensor should be 4 x 80 x 7 x 7. Here is the step to compute the loss:</p>
<pre><code class="lang-auto"># Flatten the batch size and 7x7 feature map to one dimension
out = out.permute(0, 2, 3, 1).contiguous().view(-1, class_numer) # size is 196 x 80
# What about the order? Why you did permute? And what the *ell is contiguous?
# Quick answer is: The order of dimension one is as expected, which is
# First row of the 7x7 feature map of first batch
# Second row of feature map of first batch
# Thrid row of first batch
# ...
# First row of second batch
# ...
# Last row of last batch

# You can refer to https://github.com/pytorch/pytorch/issues/2013
# for how pytorch's `view` works, and why I put a permute and contiguous there


# Now let's regard the `out` as we 196 predictions 
# and for every prediction, we have 80 classes.
# And I believe that you can arrange the same order 
# targets from the ground truth, which should be
# a vector of 196 composed by real class numbers.
targets = tatgets_vector() # implement this function

# get loss, no need to do softmax
loss = F.cross_entropy(out, target)

</code></pre>
<p>I have re-implemented <a href="https://github.com/louis-she/sfd.pytorch" rel="nofollow noopener">S3FD</a>. It’s pretty like SSD, both are anchor(default box) based detector. Here is what I done for this <a href="https://github.com/louis-she/sfd.pytorch/blob/master/trainer.py#L105" rel="nofollow noopener">https://github.com/louis-she/sfd.pytorch/blob/master/trainer.py#L105</a></p>

isalirezag: <p>Thank you!<br>
I was always confuse why people do that!!</p>
<p>Just for the clarification, if i have several anchor boxes (lets say 2 for example), my prediction (and ground truth) will be like Bx2CxDxD instead of BxCxDxD, can I still use the aforementioned method to compute the loss?</p>

chenglu: <p>Of course, just make sure the order of the ground truth and the order of the predictions is the same. The right way to reshape could be:</p>
<pre><code class="lang-auto"># if your output is B x 2 x C x D x D
output.permute(0, 3, 4, 1, 2).contiguous().view(-1, C)
</code></pre>

isalirezag: <p>Thanks a lot! Very useful</p>

isalirezag: <p>I made those changes, but I found a new error.<br>
Lets say 66 is the class number and feature maps where 8x8 = 64<br>
after modifying the predictions and GTs I have:<br>
input and target.</p>
<pre><code>print(input.type())
print(target.type())
print(input.size())
print(target.size())
</code></pre>
<p>torch.cuda.FloatTensor<br>
torch.FloatTensor<br>
torch.Size([64, 66])<br>
torch.Size([64, 66])</p>
<p>So I read a couple of other posts and realized that I should convert it to LongTensor.</p>
<pre><code>target =target.type(torch.LongTensor).cuda()


print(input.type())
print(target.type())
print(input.size())
print(target.size())
</code></pre>
<p>torch.cuda.FloatTensor<br>
torch.cuda.LongTensor<br>
torch.Size([64, 66])<br>
torch.Size([64, 66])</p>
<p>but still when i want to compute the loss i face this:</p>
<pre><code>loss = F.cross_entropy(input, target)
</code></pre>
<blockquote>
<hr>
<p>RuntimeError                              Traceback (most recent call last)<br>
 in ()<br>
24     print(input.size())<br>
25     print(target.size())<br>
—&gt; 26     loss = F.cross_entropy(input, target)<br>
27</p>
<p>~/anaconda3/lib/python3.6/site-packages/torch/nn/functional.py in cross_entropy(input, target, weight, size_average, ignore_index, reduce)<br>
1440         &gt;&gt;&gt; loss.backward()<br>
1441     “”"<br>
 → 1442     return nll_loss(log_softmax(input, 1), target, weight, size_average, ignore_index, reduce)<br>
1443<br>
1444</p>
<p>~/anaconda3/lib/python3.6/site-packages/torch/nn/functional.py in nll_loss(input, target, weight, size_average, ignore_index, reduce)<br>
1330                          .format(input.size(0), target.size(0)))<br>
1331     if dim == 2:<br>
 → 1332         return torch._C._nn.nll_loss(input, target, weight, size_average, ignore_index, reduce)<br>
1333     elif dim == 4:<br>
1334         return torch._C._nn.nll_loss2d(input, target, weight, size_average, ignore_index, reduce)</p>
<p>RuntimeError: multi-target not supported at /opt/conda/conda-bld/pytorch_1524586445097/work/aten/src/THCUNN/generic/ClassNLLCriterion.cu:16</p>
</blockquote>
<p>Can you please let me know if you have any suggestion in this regard…</p>

chenglu: <p>As I said, the target should be a vector of class number, not one hot encoded.<br>
In your case, the target should be just 64, not (64, 66).</p>

n0obcoder: <p>target having the shape [batch_size, height, width] is requires for pixel wise classification (segmentation), right ?</p>

ptrblck: <p>For multi-class classification and e.g. <code>nn.CrossEntropyLoss</code>, the shape is right.</p>

Anuj: <p>Hi</p>
<p>Given the data set your task is to predict the tags associated with a<br>
recipe.<br>
Input - A dataframe with the<br>
columns:(”cooking_method”,”cuisine”,”ingredients”,”prep_time”,”recipe_name”,”serves”<br>
)<br>
Target Column - tags<br>
Evaluation Criteria - Cross Entropy Loss<br>
Deliverables : A Jupyter notebook detailing the steps and approach. Design your<br>
transformation/pipeline so that we can pass a test data frame to get the prediction.</p>