Here is my solution to the ignore_index feature, not sure this is 100% correct. I added some comment so you can understand the logic behind. This is simple masking of the tensors.
def dice_loss(output, target, weights=1, ignore_index=None):
    encoded_target = output.data.clone().zero_()
    if ignore_index is not None:
        # mask of invalid label
        mask = target == -1
        # clone target to not affect the original 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."

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

    dice = 2 * (num / (den1 + den2).sum(dim=3).sum(dim=2)) * weights
    return -dice.sum() / dice.size(0)