I am new to pytorch.  I’m working on semantic segmentation, so I like to use the dice_loss to update the model’s parameters (Previously, I tested the model with the CrossEntropy loss function and works reasonably).
Here, some code:

for epoch in range(epochs):
for inputs, labels in train_loader:
inputs, labels = inputs.to(device), labels.to(device)
optimizer.zero_grad()
outputs = model(inputs)
_, predicted = torch.max(outputs.data, 1) # since I will work with 1s and 0s
loss = dice_loss(predicted,labels)
loss.backward()  # Backward propagation
optimizer.step()

A loss output is as like tensor(0.7531, grad_fn=<AddBackward0>), and loss.backward() does not fails, but in my test the loss never decreases after it inits.
Here my loss function in details:
def dice_loss(predicted, labels):
    """Dice coeff loss for a batch"""
    
    # both the predicted and the labels data are being one-hot encoded
    onehot_pred = torch.Tensor()
    onehot_lab = torch.Tensor()    
    for batch, data in enumerate(zip(predicted, labels)):
        # to_categorical is the KERAS adapted function
        pred = utils.to_categorical(data[0]).unsqueeze(dim=0)
        lab = utils.to_categorical(data[1]).unsqueeze(dim=0)        
        onehot_pred = torch.cat((onehot_pred,pred),dim=0)
        onehot_lab = torch.cat((onehot_lab,lab),dim=0)
    
    # calculate the loss function
    ratio = 1 / predicted.size(0) # instead to divide by the batch_size
    
    # loss accumulator
    dc = torch.tensor(0).float()
    
    # I put required gradient in order to create a grad_fn
    # without loss.backward() does not work
    onehot_pred.requires_grad = True
    onehot_lab.requires_grad = True
    
    for batch , data in enumerate(zip(onehot_pred,onehot_lab)):
        dc += dice_coeff(data[0], data[1])*ratio
    return dc

and the other function

def dice_coeff(predicted, labels):
“”“Dice coeff for a simple plane”""
eps = 0.0001
inter = torch.dot(predicted.view(-1), labels.view(-1))
union = torch.sum(predicted) + torch.sum(labels) + eps
dice_coeff = 1 - (2 * inter.float() + eps) / union.float()
return dice_coeff