You are right, weighting to 0 is also a good option, that what I did first, however I thought using mask would be simpler and faster.
def dice_loss(output, target, weights=1, ignore_index=None):
    output = output.exp()
    encoded_target = output.data.clone().zero_()
    if ignore_index is not None:
        # mask of invalid label
        mask = target == ignore_index
        # clone target to not affect the variable ?
        filtered_target = target.clone()
        # replace invalid label with whatever legal index value
        filtered_target[mask] = 0
        # one hot encoding
        encoded_target.scatter_(1, filtered_target.unsqueeze(1), 1)
        # expand the mask for the encoded target array
        mask = mask.unsqueeze(1).expand(output.data.size())
        # apply 0 to masked pixels
        encoded_target[mask] = 0
    else:
        encoded_target.scatter_(1, target.unsqueeze(1), 1)
    encoded_target = Variable(encoded_target)

    assert output.size() == encoded_target.size(), "Input sizes must be equal."
    assert output.dim() == 4, "Input must be a 4D Tensor."

    numerator = (output * encoded_target).sum(dim=3).sum(dim=2)
    denominator = output.pow(2) + encoded_target
    if ignore_index is not None:
        # exclude masked values from den1
        denominator[mask] = 0

    dice = 2 * (numerator / denominator.sum(dim=3).sum(dim=2)) * weights
    return dice.sum() / dice.size(0)

Ignore_index is negative, it’s also the value specified to nll_loss. Those labels are ignored from the loss.
This function tends to plus infinity if the similarity improves, I can’t think of a way to optimize this, loss = -dice(output, target) would mean having a negative loss from the start, it would not converge as the dice would tend to minus infinity…