IndexError: Target 24000 is out of bounds

Tried to train a model for Image segmentation. Used a pretrained model by torchvision FCN-Resnet101 and changed the final two layers to have a model for output number of classes = 30.

I chose the Network as:

def Net():
print(“Loading in pretrained network …”)
model = models.segmentation.fcn_resnet101(pretrained=True).eval().to(device)
for param in model.parameters():
param.requires_grad = False

model.classifier = nn.Sequential(
    nn.Conv2d(2048, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False),
    nn.BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True),
    nn.ReLU(),
    nn.Dropout(p=0.1, inplace=False),
    nn.Conv2d(512, 30, kernel_size=(1, 1), stride=(1, 1))
    )
model.aux_classifier = nn.Sequential(
    nn.Conv2d(1024, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False),
    nn.BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True),
    nn.ReLU(),
    nn.Dropout(p=0.1, inplace=False),
    nn.Conv2d(256, 30, kernel_size=(1, 1), stride=(1, 1))
    )
print(model)
return model

and the training was done in such a manner:

def train_model(model, train_loader, val_loader, epochs=1):
learning_rate = 1e-4
optimizer = optim.Adam(model.aux_classifier.parameters(), lr=learning_rate)

model = model.to(device)  # move the model parameters to CPU/GPU
for e in range(epochs):
    print("Epoch: ", e)
    for t, (x, y) in enumerate(train_loader):
        model.train()
        x = x.to(device)
        y = y.type(torch.LongTensor)
        y = y.to(device)
        y = y.squeeze(1)

        scores = model(x)['out']
        loss = F.cross_entropy(scores, y)
        torch.cuda.empty_cache()
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

        if t % 100 == 0:
            print('Iteration %d, loss = %.4f' % (t, loss.item()))
            check_val_accuracy(val_loader, model)
            print()

I got this error:

Traceback (most recent call last):
File “main.py”, line 341, in module
main()
File “main.py”, line 334, in main
train_model(model, train_loader, val_loader, epochs=3)
File “main.py”, line 125, in train_model
loss = F.cross_entropy(scores, y)
File “/media/vicknesh/Studies/CSCI508/Project/venv/lib/python3.6/site-packages/torch/nn/functional.py”, line 2021, in cross_entropy
return nll_loss(log_softmax(input, 1), target, weight, None, ignore_index, None, reduction)
File “/media/vicknesh/Studies/CSCI508/Project/venv/lib/python3.6/site-packages/torch/nn/functional.py”, line 1840, in nll_loss
ret = torch._C._nn.nll_loss2d(input, target, weight, _Reduction.get_enum(reduction), ignore_index)
IndexError: Target 24000 is out of bounds.

Even though my output number of classes are 30 my targets are going out of bounds and that too 24000. I even tried CrossEntropyLoss(). What mistake can you see?

How did you define your target and could you check the min and max values for it?
For a segmentation use case the target should have the shape [batch_size, height, width] and contain the class indices in the range [0, nb_classes-1].

Thanks, looks like my class indices aren’t in the range as specfied. I printed the minimum and maximum values of my label for few iterations and this is what I got:

tensor(1) tensor(33008)
tensor(0) tensor(33004)
tensor(0) tensor(33001)
tensor(0) tensor(33003)
tensor(1) tensor(33003)
tensor(0) tensor(33001)
tensor(1) tensor(33000)
tensor(1) tensor(33000)
tensor(0) tensor(33003)
tensor(0) tensor(33000)
tensor(0) tensor(33007)
tensor(0) tensor(33005)
tensor(0) tensor(33004)
tensor(0) tensor(33006)
tensor(0) tensor(33000)
tensor(0) tensor(33001)
tensor(0) tensor(33000)
tensor(0) tensor(33005)
tensor(1) tensor(33001)
tensor(0) tensor(33002)
tensor(0) tensor(33001)
tensor(0) tensor(33002)
tensor(0) tensor(33000)
tensor(0) tensor(33001)
tensor(1) tensor(33000)
tensor(1) tensor(33000)
tensor(0) tensor(33000)
tensor(0) tensor(33003)
tensor(0) tensor(33006)
tensor(0) tensor(33002)
tensor(1) tensor(33002)
tensor(1) tensor(33005)
tensor(0) tensor(33002)
tensor(1) tensor(33000)
tensor(1) tensor(33000)
tensor(0) tensor(33003)
tensor(1) tensor(33006)
tensor(1) tensor(33000)
tensor(1) tensor(27000)
tensor(1) tensor(33003)
tensor(1) tensor(33001)
tensor(0) tensor(33002)
tensor(0) tensor(33000)
tensor(1) tensor(33002)
tensor(0) tensor(33000)
tensor(1) tensor(33001)
tensor(0) tensor(33002)
tensor(1) tensor(33001)
tensor(0) tensor(33005)
tensor(0) tensor(33004)

How do I tackle this now?

It depends how you’ve created these targets.
Did you load these values from a file or generated them somehow?

I used the torchvision.datasets.Cityscapes to load the model.

model = Net()
model = model.to(device)
train_transform = transforms.Compose([
#transforms.RandomResizedCrop(size=224, scale=(0.9,1.0), ratio=(0.9,1.1)),
#transforms.Resize(256),
transforms.RandomHorizontalFlip(),
transforms.ToTensor(),
transforms.Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5])
])
test_transform = transforms.Compose([
#transforms.Resize(256),
#transforms.CenterCrop(224),
transforms.ToTensor(),
transforms.Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5])
])
train_dataset = torchvision.datasets.Cityscapes(root = “./Cityscapes”, split=“train”, transform=train_transform)
num_train = len(train_dataset)
val_dataset = torchvision.datasets.Cityscapes(root = “./Cityscapes”, split=“val”, transform=train_transform)
num_val = len(val_dataset)
print(“Number of training images: %d” % len(train_dataset))
print(“Number of validation images: %d” % len(val_dataset))

    batch_size = 3

    train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=batch_size, shuffle=True, num_workers=1)
    val_loader = torch.utils.data.DataLoader(val_dataset, batch_size=batch_size, shuffle=True, num_workers=1)
    test_dataset = torchvision.datasets.Cityscapes(root = "./Cityscapes", split="test", transform=test_transform)
    test_loader = torch.utils.data.DataLoader(test_dataset, batch_size=batch_size, shuffle=True, num_workers=1)
    print("Number of test images: %d" % len(test_dataset))
    torch.save(train_loader,'train_loader')
    torch.save(val_loader,'val_loader')
    torch.save(test_loader,'test_loader')
    train_model(model, test_loader, val_loader, epochs=3)

How does your folder structure in ./Cityscapes look?
I’m not deeply familiar with this dataset, but it seems the default target_type is set as 'instance'.
Do you know, how these targets are defined internally?

Yes, target_type is set to instance. What should I be using. I don’t know the background of these.
The cityscapes class is as below:

torchvision.datasets. Cityscapes ( root , split=‘train’ , mode=‘fine’ , target_type=‘instance’ , transform=None , target_transform=None , transforms=None )[SOURCE]

Cityscapes Dataset.

Parameters

  • root ( string ) – Root directory of dataset where directory leftImg8bit and gtFine or gtCoarse are located.
  • split ( string , optional ) – The image split to use, train , test or val if mode=”fine” otherwise train , train_extra or val
  • mode ( string , optional ) – The quality mode to use, fine or coarse
  • target_type ( string or list , optional ) – Type of target to use, instance , semantic , polygon or color . Can also be a list to output a tuple with all specified target types.
  • transform ( callable , optional ) – A function/transform that takes in a PIL image and returns a transformed version. E.g, transforms.RandomCrop
  • target_transform ( callable , optional ) – A function/transform that takes in the target and transforms it.
  • transforms ( callable , optional ) – A function/transform that takes input sample and its target as entry and returns a transformed version.

Edit: I just saw that we have a target_type called semantic. I’ll try using it.