ValueError: empty range for randrange() (0,-14, -14)

I was building an Image Classification model using PyTorch, where I came across this error while training.

ValueError: empty range for randrange() (0,-14, -14)

I am using the dataset available on Kaggle here.
I wasn’t able to identify what might be the issue here.
I attaching the relevant code:

Model Definition:

class Model(nn.Module):
    def __init__(self):
        super(Model, self).__init__()
        self.conv1 = nn.Conv2d(3, 16, kernel_size = (3, 3))
        self.conv2 = nn.Conv2d(16, 64, kernel_size = (3, 3))
        self.conv3 = nn.Conv2d(64, 256, kernel_size = (3, 3))
        self.maxpool = nn.MaxPool2d(2, stride = 3)
        self.flatten = nn.Flatten()
        self.fc1 = nn.Linear(4*4*256, 256)
        self.fc2 = nn.Linear(256, 32)
        self.fc3 = nn.Linear(32, 10)
            
    def forward(self, image):
        image = F.relu(self.conv1(image))
        image = self.maxpool(image)
        image = F.relu(self.conv2(image))
        image = self.maxpool(image)
        image = F.relu(self.conv3(image))
        image = self.maxpool(image)
        
        image = self.flatten(image)
        
        image = F.relu(self.fc1(image))
        image = F.relu(self.fc2(image))
        image = image.reshape(image.shape[0], -1)
        image = F.relu(self.fc3(image))
        
        return image
        
model = Model()

And the training script:

device = 'cpu'
model = model.to(device)
optimizer = torch.optim.Adam(model.parameters(), lr = 0.01)
criterion = nn.CrossEntropyLoss()

epochs = 5
training_loss = []
accuracy = []
thresh = 50
iters = 0
total_loss = 0
for e in range(epochs):
    for sample, label in image_loader:
        sample, label = sample.to(device), label.to(device)
        optimizer.zero_grad()
        output = model(sample)
        loss = criterion(output, label)
        loss.backward()
        optimizer.step()
        total_loss += loss.item()
        if iters%thresh == 0:
            pred = torch.argmax(output, dim = 1)
            correct = pred.eq(label)
            acc = torch.mean(correct.float())
            print('[Epoch {}/{}] Iteration {} -> Train Loss: {:.4f}, Accuracy: {:.3f}'.format(e+1, epochs, iters, loss/thresh, acc))
            training_loss.append(loss)
            accuracy.append(acc)
            total_loss = 0
        iters += 1
plt.plot(loss_list, label='loss')
plt.plot(acc_list, label='accuracy')
plt.legend()
plt.title('training loss and accuracy')
plt.show()

Also, the logs:

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-22-db0270104083> in <module>
     11 total_loss = 0
     12 for e in range(epochs):
---> 13     for sample, label in image_loader:
     14         sample, label = sample.to(device), label.to(device)
     15         optimizer.zero_grad()

/opt/conda/lib/python3.7/site-packages/torch/utils/data/dataloader.py in __next__(self)
    361 
    362     def __next__(self):
--> 363         data = self._next_data()
    364         self._num_yielded += 1
    365         if self._dataset_kind == _DatasetKind.Iterable and \

/opt/conda/lib/python3.7/site-packages/torch/utils/data/dataloader.py in _next_data(self)
    401     def _next_data(self):
    402         index = self._next_index()  # may raise StopIteration
--> 403         data = self._dataset_fetcher.fetch(index)  # may raise StopIteration
    404         if self._pin_memory:
    405             data = _utils.pin_memory.pin_memory(data)

/opt/conda/lib/python3.7/site-packages/torch/utils/data/_utils/fetch.py in fetch(self, possibly_batched_index)
     42     def fetch(self, possibly_batched_index):
     43         if self.auto_collation:
---> 44             data = [self.dataset[idx] for idx in possibly_batched_index]
     45         else:
     46             data = self.dataset[possibly_batched_index]

/opt/conda/lib/python3.7/site-packages/torch/utils/data/_utils/fetch.py in <listcomp>(.0)
     42     def fetch(self, possibly_batched_index):
     43         if self.auto_collation:
---> 44             data = [self.dataset[idx] for idx in possibly_batched_index]
     45         else:
     46             data = self.dataset[possibly_batched_index]

<ipython-input-16-449d83383611> in __getitem__(self, idx)
     10     def __getitem__(self, idx):
     11         image = Image.open(self.data['filename'][idx])
---> 12         image = self.transform(image)
     13         image = image.numpy().astype('float32')
     14         label = self.data['labels'][idx]

/opt/conda/lib/python3.7/site-packages/torchvision/transforms/transforms.py in __call__(self, img)
     59     def __call__(self, img):
     60         for t in self.transforms:
---> 61             img = t(img)
     62         return img
     63 

/opt/conda/lib/python3.7/site-packages/torchvision/transforms/transforms.py in __call__(self, img)
    518             img = F.pad(img, (0, self.size[0] - img.size[1]), self.fill, self.padding_mode)
    519 
--> 520         i, j, h, w = self.get_params(img, self.size)
    521 
    522         return F.crop(img, i, j, h, w)

/opt/conda/lib/python3.7/site-packages/torchvision/transforms/transforms.py in get_params(img, output_size)
    496             return 0, 0, h, w
    497 
--> 498         i = random.randint(0, h - th)
    499         j = random.randint(0, w - tw)
    500         return i, j, th, tw

/opt/conda/lib/python3.7/random.py in randint(self, a, b)
    220         """
    221 
--> 222         return self.randrange(a, b+1)
    223 
    224     def _randbelow(self, n, int=int, maxsize=1<<BPF, type=type,

/opt/conda/lib/python3.7/random.py in randrange(self, start, stop, step, _int)
    198             return istart + self._randbelow(width)
    199         if step == 1:
--> 200             raise ValueError("empty range for randrange() (%d,%d, %d)" % (istart, istop, width))
    201 
    202         # Non-unit step argument supplied.

ValueError: empty range for randrange() (0,-14, -14)

I guess you are using a random crop transformation, which apparently fails.
Could you post the code for the Dataset and the transformations you are passing to it?

1 Like

Yes, I am using the RandomCrop transformation
Here is the code:

class ImageDataset(Dataset):
    def __init__(self, data, transform = None):
        self.data = data
        if transform != None:
            self.transform = transform
        else:
            self.transform = transforms.Compose([transforms.ToTensor()])
    def __len__(self):
        return len(self.data)
    def __getitem__(self, idx):
        image = Image.open(self.data['filename'][idx])
        image = self.transform(image)
        image = image.numpy().astype('float32')
        label = self.data['labels'][idx]
        return image, label
    
transform = transforms.Compose([
    transforms.ColorJitter(),
    transforms.RandomCrop(128),
    transforms.RandomHorizontalFlip(), 
    transforms.RandomVerticalFlip(),
    transforms.ToTensor()
])

Are you making sure the images are not smaller than the crop size of 128?
I get a similar issue, if I pass small images to the transformation:

img = TF.to_pil_image(torch.randn(3, 50, 50))
crop = transforms.RandomCrop(128)
out = crop(img)
> RuntimeError: random_ expects 'from' to be less than 'to', but got from=0 >= to=-77

The error message might be different, if you are using an older torchvision, since the random size sampling was changed in this PR to torch.randint.

I figured it out. The image size was 150X150. It is working now. I replaced RandomCrop with Resize and the model is now training.

Can you help me on this ? Loss remains constant/unchanged