Binary Cross Entropy with logits does not work as expected
Info about binary cross entropy with logits
pytorch - binary_cross_entropy_with_logits produces negative output - Stack Overflow
deep learning - How is cross entropy loss work in pytorch? - Stack Overflow
I've ran into this multiple times, each time reason was labels are not between 0 and 1
The following code block is proposed by G. Hinton in his course: http://www.cs.toronto.edu/~tijmen/csc321/slides/lecture_slides_lec6.pdf
optimizer = optim.RMSprop(net.parameters(), lr=0.005, weight_decay=1e-8)
if net.n_classes > 1:
criterion = nn.CrossEntropyLoss()
else:
criterion = nn.BCEWithLogitsLoss()
Then you will need to use sigmoid (Torch Functional: F.sigmoid) in a similar manner as the code example below:
for isample, sample in enumerate(ds):
mask_torch = net2(sample['image'][None, :, :, :].type(torch.cuda.FloatTensor))
mask = (F.sigmoid(mask_torch.type(torch.cuda.FloatTensor)) > 0.4925099).type(torch.FloatTensor)
print(mask)
for ichan in range(3):
ax[isample, ichan].imshow(sample['image'][ichan].cpu())
ax[isample, 3].imshow(sample['mask'][0].cpu())
ax[isample, 4].imshow(mask[0, 0].cpu().detach().numpy())
Place the sigmoid at the end after al the layers. It will look something like this:
For sigmoid, It will look something like this:
def forward(self, x):
#print(x.shape)
x = self.layer_1(x)
x = self.layer_2(x)
x = self.layer_3(x)
logits = F.sigmoid(self.outc(x))
return logits
is there an equivalent PyTorch loss function for TensorFlow's
softmax_cross_entropy_with_logits?
torch.nn.functional.cross_entropy
This takes logits as inputs (performing log_softmax internally). Here "logits" are just some values that are not probabilities (i.e. not necessarily in the interval [0,1]).
But, logits are also the values that will be converted to probabilities.
If you consider the name of the tensorflow function you will understand it is pleonasm (since the with_logits part assumes softmax will be called).
In the PyTorch implementation looks like this:
loss = F.cross_entropy(x, target)
Which is equivalent to :
lp = F.log_softmax(x, dim=-1)
loss = F.nll_loss(lp, target)
It is not F.binary_cross_entropy_with_logits because this function assumes multi label classification:
F.sigmoid + F.binary_cross_entropy = F.binary_cross_entropy_with_logits
It is not torch.nn.functional.nll_loss either because this function takes log-probabilities (after log_softmax()) not logits.
A solution
from thexp.calculate.tensor import onehot
from torch.nn import functional as F
import torch
logits = torch.rand([3,10])
ys = torch.tensor([1,2,3])
targets = onehot(ys,10)
assert F.cross_entropy(logits,ys) == -torch.mean(torch.sum(F.log_softmax(logits, dim=1) * targets, dim=1))
onehot function:
def onehot(labels: torch.Tensor, label_num):
return torch.zeros(labels.shape[0], label_num, device=labels.device).scatter_(1, labels.view(-1, 1), 1)