Invalid index at scatter?

I’m trying to implement scatter_ in my custom loss function:

encoded_target = input.data.clone().zero_()
encoded_target.scatter_(1, target.unsqueeze(1), 1)

input is the output from my CNN network and is of the shape [1,1,32,64,64] and target is the ground truth used to calculate the loss, it has the shape [1,32,64,64], hence the unsqueeze(1) to bring it to the same shape as input.

input is of type float32 and target is of type long.

I get the following error at scatter_:

RuntimeError: Invalid index in scatter at c:\new-builder_2\win-wheel\pytorch\aten\src\th\generic/THTensorMath.cpp:703

Ive checked the documentation on this and my implementation is correct, Is there any reason this is not working?

P.S. I noticed that if I change the dimension in scatter_ it works:

encoded_target.scatter_(2, target.unsqueeze(1), 1)

But this is not what i want, why is working for dimension 2 and failing for 1?

Thanks

2 Likes

I couldnt get the scatter_ to work. As a work around I managed to create my target using a thesholding method:

where_ones = torch.ones(target.shape, dtype=torch.long) 
where_zeros = torch.zeros(target.shape, dtype=torch.long)
target_ = torch.where(target > 0.1, where_ones, where_zeros)
target = torch.unsqueeze(target_, 0).float()

This works and gives the loss output but I’m not sure if this is the preferred method.
Is what what I am doing equivalent to the output produced by scatter_?
I read in one of the docs that for target is is advised to use the scatter_ method as this was the tensor is differentiable and autograd can be utilized. Or was this the case for previous versions of pytorch?

I’m not sure, how you would like to apply scatter in this case, as dim1 only is of size 1.
You would get this operation:

self[i][index[i][j][k]][k] = src[i][j][k] # if dim == 1

, which means that your scatter index (target in your case` can only hold zeros.
Other values will yield an invalid index.

Could you post a small sample with values and how the result should look like?

1 Like

Sorry, I found this code online for DiceLoss and wanted to use it in my code, below is the full code for DiceLoss:

    def forward(self, input, target):
        weights = 1
        encoded_target = input.data.clone().zero_()
        encoded_target.scatter_(1, target.unsqueeze(1), 1)
        # encoded_target = Variable(encoded_target)
        assert input.size() == encoded_target.size(), "Input sizes must be equal."
        assert input.dim() == 5, "Input must be a 4D Tensor."
        num = (input * encoded_target).sum(dim=4).sum(dim=3).sum(dim=2)
        den1 = input.pow(2).sum(dim=4).sum(dim=3).sum(dim=2)
        den2 = encoded_target.pow(2).sum(dim=4).sum(dim=3).sum(dim=2)
        dice = (2 * num / (den1 + den2)) * weights
        return ((1-dice.sum()) / dice.size(1)) / 5

I want to create a target tensor to calculate the loss against. Thats why I thought if I create it in the same was as in my second post will it be the same thing as scatter?

I assume scatter here is trying to do the same thing…

@farazk86
Hi, I am working on a code and I have run to the same error derivating form the loss function. This link explains my error https://github.com/michuanhaohao/reid-strong-baseline/issues/120. Did you find a solution for fixing the error?