"binary_cross_entropy" not implemented for 'Long'

Julien_Guegan: <p>Hello, I am implementing a segmentation task with masks and images in input and one class in output. I am trying to use the binary cross entropy from pytorch but I have this error :</p>
<p><strong>&gt; RuntimeError: “binary_cross_entropy” not implemented for 'Long’</strong></p>
<p>Indeed, I have formatted my mask as a long type, otherwise this message appear from the loss :</p>
<p><strong>&gt; RuntimeError: Found dtype Float but expected Long</strong></p>
<p>Does someone already have this error and know from where it come from ?<br>
<em>Note that I am in torch ‘1.6.0’</em></p>
<p>Thank you in advance</p>

ptrblck: <p><code>binary_cross_entropy</code> expects <code>FloatTensor</code>s as the model output and target as seen here:</p>
<pre><code class="lang-python">F.binary_cross_entropy(torch.sigmoid(torch.randn(10, 10)), torch.rand(10, 10)) # works
F.binary_cross_entropy(torch.sigmoid(torch.randn(10, 10)), torch.rand(10, 10).long()) # RuntimeError: Found dtype Long but expected Float
</code></pre>
<p>Are you sure the second <code>RuntimeError</code> is raised by this loss function and not <code>nn.CrossEntropyLoss</code>?</p>

Julien_Guegan: <p>Well yes I am using <code>nn.BCELoss()</code>, but it seems to call <code>binary_cross_entropy</code> as in the error list there is :</p>
<pre><code class="lang-auto">
  File "C:\Users\gueganj\Miniconda3\envs\pytorch_env\lib\site-packages\torch\nn\modules\loss.py", line 529, in forward
    return F.binary_cross_entropy(input, target, weight=self.weight, reduction=self.reduction)

  File "C:\Users\gueganj\Miniconda3\envs\pytorch_env\lib\site-packages\torch\nn\functional.py", line 2484, in binary_cross_entropy
    input, target, weight, reduction_enum)

RuntimeError: Found dtype Float but expected Long
</code></pre>
<p>Actually, I am not really sure to understand the difference between using nn or functionnal, <strong>Is there any subtleties to know here to make it work ?</strong></p>
<p><em>Also note that output for the dtype of my tensors are torch.int64</em></p>

ptrblck: <p>The error message is (wrongly) raised, if you pass the <code>input</code> as a <code>LongTensor</code>, which won’t work since gradients aren’t calculated for int/long types.<br>
How are you creating the <code>input</code> to this loss function?<br>
If you are calling <code>output.long()</code> on the model output, note that this operation will detach the tensor from the computation graph.</p>

Julien_Guegan: <p>First, I format my mask in 1 and 0 (cause when loading, values are 255 and some images noise/artefact appear) :</p>
<pre><code class="lang-auto">mask = np.where(mask&gt;mask.mean(), 1, 0)
mask = torch.from_numpy(mask) 
mask = mask.long()
</code></pre>
<p>It is now <strong>torch.int64</strong>, should I parse it to float ?</p>
<p>Then, for predictions, I do :</p>
<pre><code class="lang-auto">out = model(inputs)
_, predictions = torch.max(out, 1)
</code></pre>
<p>prediction is now a <strong>torch.int64</strong>, should I parse the result in float also here ? Should I do something like :</p>
<pre><code class="lang-auto">predictions = predictions.float()
predictions.requires_grad = True
</code></pre>
<p>?</p>

ptrblck: <aside class="quote no-group" data-username="Julien_Guegan" data-post="5" data-topic="97712">
<div class="title">
<div class="quote-controls"></div>
<img loading="lazy" alt="" width="24" height="24" src="https://discuss.pytorch.org/user_avatar/discuss.pytorch.org/julien_guegan/48/29247_2.png" class="avatar"> Julien_Guegan:</div>
<blockquote>
<p>It is now <strong>torch.int64</strong> , should I parse it to float ?</p>
</blockquote>
</aside>
<p>It depends what your use case is.<br>
Based on this code:</p>
<pre data-code-wrap="python"><code class="lang-python"> out = model(inputs)
_, predictions = torch.max(out, 1)
</code></pre>
<p>it seems you are dealing with a multi-class classification (or segmentation) and the <code>out</code> tensor would have the shape <code>[batch_size, nb_classes, *]</code>.<br>
If that’s the case, you should use <code>nn.CrossEntropyLoss</code> and the target tensor should be a <code>LongTensor</code> in the shape <code>[batch_size, *]</code> containing the class indices in the range <code>[0, nb_classes-1]</code>.</p>
<p>On the other hand you are using <code>nn.BCEWithLogitsLoss</code>, which is used for a binary or multi-label classification.</p>
<p>Could you explain your use case a bit?</p>

Julien_Guegan: <p>I think you just raise a mistake from my side ! Indeed, I want to do a binary segmentation but I think wrongly design my model by outputting 2 values instead of 1 and then taking the max. <em>I am kind of new to the field so an error happened quickly …</em> <img src="https://discuss.pytorch.org/images/emoji/apple/sweat.png?v=9" title=":sweat:" class="emoji" alt=":sweat:"></p>
<p>So what I should do is have only one output from my model (a softmax probability or a logit ?) and then giving to the <code>nn.BCELoss()</code> ?</p>
<p>Thank you for your big help (as always)</p>

ptrblck: <p>You can</p>
<ul>
<li>use a single output unit without any activation function at the end and lass this logit to <code>nn.BCEWithLogitsLoss</code>. For this the targets should have the same shape as the model output and be <code>FloatTensor</code>s. To get the predicted label you can apply <code>torch.sigmoid</code> and use a threshold via <code>preds = output &gt; threshold</code>.</li>
<li>use two output units (treat the binary segmentation as a multi-class segmentation) and pass the logits to <code>nn.CrossEntropyLoss</code>. The target would be the <code>LongTensor</code> as described before. To get the predicted classes you can use <code>preds = torch.argmax(output, dim=1)</code>.</li>
</ul>

Julien_Guegan: <p>Thank you it is indeed what I should have done ! (Still the error message was a bit confusing in my case)</p>

Julien_Guegan: <p>But do I have to expect different result between this two methods (BCE+threshold and CE+argmax) ? <em>assuming my threshold is not badly chosen</em></p>

ptrblck: <p>I would expect some differences, since the model architecture would have to be changed and also these loss functions use a different loss calculation.<br>
E.g. for a binary classification your last layer would have 2 output units using <code>nn.CrossEntropyLoss</code>, while only one using <code>nn.BCEWithLogitsLoss</code>. While this might be a “small” difference I would still expect to get different results.</p>

siamak: <p>Hi ptrblck,</p>
<p>Thanks for the solution. It took me ages to find this page and implement the solution. This is not obvious and totally different from other common AI/ML frameworks. Is there a webpage/document that someone can access this information in the first place?</p>
<p>It will be great if such an examples are added to the PyTorch tutorials/examples.</p>
<p>Siamak</p>

ptrblck: <p>If you mean the expected shapes and <code>dtypes</code> for each loss function, you could check the docs as they explain each expected input. If you think the docs are lacking a proper explanation, all feedback is welcome.</p>

siamak: <p>For me it was <code>BCEWithLogitsLoss</code> and not <code>BCE</code> and then all the other instructions which like"</p>
<p>" For this the targets should have the same shape as the model output and be <code>FloatTensor</code>s. To get the predicted label you can apply <code>torch.sigmoid</code> and use a threshold via <code>preds = output &gt; threshold</code>"</p>
<p>Thanks anyway.</p>