List index out of range error for predict()

Hi
When I run this code:

learn_inf = load_learner("model.pkl")
print(learn_inf.predict('fish.jpg'))

I get this error:

Traceback (most recent call last):
   File "...\test.py", line 105, in <module>
     print(learn_inf.predict('fish.jpg'))
   File "...\venv\lib\site-packages\fastai\learner.py", line 266, in predict
     dec = self.dls.decode_batch(inp + tuplify(dec_preds))[0]
   File "...\venv\lib\site-packages\fastai\data\core.py", line 80, in decode_batch
     def decode_batch(self, b, max_n=9, full=True): return self._decode_batch(self.decode(b), max_n, full)
   File "...\venv\lib\site-packages\fastai\data\core.py", line 79, in decode
     def decode(self, b): return to_cpu(self.after_batch.decode(self._retain_dl(b)))
   File "...\venv\lib\site-packages\fastai\data\core.py", line 58, in _retain_dl
     if not getattr(self, '_types', None): self._one_pass()
   File "...\venv\lib\site-packages\fastai\data\core.py", line 51, in _one_pass
     b = self.do_batch([self.do_item(None)])
   File "...\venv\lib\site-packages\fastai\data\load.py", line 133, in do_item
     try: return self.after_item(self.create_item(s))
   File "...\venv\lib\site-packages\fastai\data\load.py", line 140, in create_item
     if self.indexed: return self.dataset[s or 0]
   File "...\venv\lib\site-packages\fastai\data\core.py", line 333, in __getitem__
     res = tuple([tl[it] for tl in self.tls])
   File "...\venv\lib\site-packages\fastai\data\core.py", line 333, in <listcomp>
     res = tuple([tl[it] for tl in self.tls])
   File "...\venv\lib\site-packages\fastai\data\core.py", line 297, in __getitem__
     res = super().__getitem__(idx)
   File "...\venv\lib\site-packages\fastcore\foundation.py", line 111, in __getitem__
     def __getitem__(self, idx): return self._get(idx) if is_indexer(idx) else L(self._get(idx), use_list=None)
   File "...\venv\lib\site-packages\fastcore\foundation.py", line 115, in _get
     if is_indexer(i) or isinstance(i,slice): return getattr(self.items,'iloc',self.items)[i]
 IndexError: list index out of range

In addition, when I change the code to:

files = get_image_files(TEST_FOLDER)
test_dl = learn_inf.dls.test_dl(files)
preds = learn_inf.get_preds(dl=test_dl)

I get these errors:
AttributeError: Can't get attribute 'func1' on <module '__main__' (built-in)>
and

...
  File "...\conda3\lib\multiprocessing\reduction.py", line 60, in dump
    ForkingPickler(file, protocol).dump(obj)
BrokenPipeError: [Errno 32] Broken pipe

However, I’ve included def func1: ... in this code (before load_learner) in the same way as in the network training code.
And another strange thing happens when I execute it: It seems that the entire program runs twice before getting that error! For example, I have print('hi there') in line 1 of a .py file while the “get_preds” is in line 100. When I execute the file I can see hi there twice in the output!

I’m rather new to fastai and I might be making some mistakes… It would be much appreciated if someone could help me.

(I’m using fastai version 2.3.1 and fastcore version 1.3.20)

I am not sure what is happening looking at the code snippets. Is it possible to share code that reproduces the error. It will be a lot easier to help.

Thank you for the reply.
This is almost the whole code:

import cv2
from fastai.data.all import *
from fastai.vision.all import *
import numpy

print('Make sure cuda is installed:', torch.cuda.is_available())
print('Make sure cudnn is enabled:', torch.backends.cudnn.enabled)

IMG_SIZE = 448
sigmaX = 15

def sensitivity(y_hat, y):
    new_y_hat = torch.argmax(y_hat.cpu(), 1)
    new_y_hat_hat = new_y_hat.clone()
    new_y_hat_hat[new_y_hat == 1] = 0
    new_y_hat_hat[new_y_hat == 2] = 1
    new_y_hat_hat[new_y_hat == 3] = 1
    new_y_hat_hat[new_y_hat == 4] = 1
    new_y = y.clone()
    new_y[y == 1] = 0
    new_y[y == 2] = 1
    new_y[y == 3] = 1
    new_y[y == 4] = 1
    y_true=new_y.cpu())
    return Recall(pos_label=1)(preds=new_y_hat_hat, targs=new_y)

def get_x(r): return r['path']
def get_y(r): return r['level']

def crop_image_from_gray(img, tol=7):
    if img.ndim == 2:
        mask = img > tol
        return img[np.ix_(mask.any(1), mask.any(0))]
    elif img.ndim == 3:
        gray_img = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
        mask = gray_img > tol

        check_shape = img[:, :, 0][np.ix_(mask.any(1), mask.any(0))].shape[0]
        if (check_shape == 0):  
            return img 
        else:
            img1 = img[:, :, 0][np.ix_(mask.any(1), mask.any(0))]
            img2 = img[:, :, 1][np.ix_(mask.any(1), mask.any(0))]
            img3 = img[:, :, 2][np.ix_(mask.any(1), mask.any(0))]
            img = np.stack([img1, img2, img3], axis=-1)
        return img

def func1(image: PILImage):
    image = numpy.array(image)
    image = crop_image_from_gray(image)
    image = cv2.resize(image, (IMG_SIZE, IMG_SIZE))
    image = cv2.addWeighted(image, 4, cv2.GaussianBlur(image, (0, 0), sigmaX), -4, 128)
    return Image.fromarray(image)

def quadratic_kappa(y_hat, y):
    return torch.tensor(cohen_kappa_score(torch.argmax(y_hat.cpu(), 1), y.cpu(), weights='quadratic'), device='cuda:0')

learn_inf = load_learner("model.pkl")
print(learn_inf.predict('fish.jpg'))

The functions you see here were included in the training code as item_tfms and get_x and get_y (in DataBlock declaration) or as a metric in cnn_learner. Apparently, these functions should be included here, too.
When I run this, I get the error:

Traceback (most recent call last):
   File "...\test.py", line 105, in <module>
     print(learn_inf.predict('fish.jpg'))
   File "...\venv\lib\site-packages\fastai\learner.py", line 266, in predict
     dec = self.dls.decode_batch(inp + tuplify(dec_preds))[0]
   File "...\venv\lib\site-packages\fastai\data\core.py", line 80, in decode_batch
     def decode_batch(self, b, max_n=9, full=True): return self._decode_batch(self.decode(b), max_n, full)
   File "...\venv\lib\site-packages\fastai\data\core.py", line 79, in decode
     def decode(self, b): return to_cpu(self.after_batch.decode(self._retain_dl(b)))
   File "...\venv\lib\site-packages\fastai\data\core.py", line 58, in _retain_dl
     if not getattr(self, '_types', None): self._one_pass()
   File "...\venv\lib\site-packages\fastai\data\core.py", line 51, in _one_pass
     b = self.do_batch([self.do_item(None)])
   File "...\venv\lib\site-packages\fastai\data\load.py", line 133, in do_item
     try: return self.after_item(self.create_item(s))
   File "...\venv\lib\site-packages\fastai\data\load.py", line 140, in create_item
     if self.indexed: return self.dataset[s or 0]
   File "...\venv\lib\site-packages\fastai\data\core.py", line 333, in __getitem__
     res = tuple([tl[it] for tl in self.tls])
   File "...\venv\lib\site-packages\fastai\data\core.py", line 333, in <listcomp>
     res = tuple([tl[it] for tl in self.tls])
   File "...\venv\lib\site-packages\fastai\data\core.py", line 297, in __getitem__
     res = super().__getitem__(idx)
   File "...\venv\lib\site-packages\fastcore\foundation.py", line 111, in __getitem__
     def __getitem__(self, idx): return self._get(idx) if is_indexer(idx) else L(self._get(idx), use_list=None)
   File "...\venv\lib\site-packages\fastcore\foundation.py", line 115, in _get
     if is_indexer(i) or isinstance(i,slice): return getattr(self.items,'iloc',self.items)[i]
 IndexError: list index out of range

And when I replace the last line of the code with:

files = get_image_files('D:\...\samples')
test_dl = learn_inf.dls.test_dl(files)
preds = learn_inf.get_preds(dl=test_dl)
print(preds)

I get the errors that I’ve mentioned above ( AttributeError: Can't get attribute 'func1' on <module '__main__' (built-in)>).

And I should note that I’m running this code on a Windows system (with python 3.7) while I’ve trained the model on another system with Ubuntu OS (with python 3.8) and I no longer have access to the training dataset.

Please someone help me…
I created a new venv with the upgraded python (3.9.5) and the last versions of the packages, but nothing changed.

learn_inf = load_learner("model.pkl")
print(learn_inf.predict('fish.jpg'))

Still the same error; and I think it might be due to a bug in fastcore:

...
   File "...\venv\lib\site-packages\fastcore\foundation.py", line 115, in _get
     if is_indexer(i) or isinstance(i,slice): return getattr(self.items,'iloc',self.items)[i]
 IndexError: list index out of range

Would you fix this please? @jeremy @sgugger @muellerzr
Or please tell me what the error means? What should I do?

By the way, preds = learn_inf.get_preds(dl=test_dl) works on Linux without any errors, and I could fix it on Windows, too. It tries to create several processes, so because of the different behavior of multi-processing workers on Windows, we should wrap most of the main script’s code within if __name__ == '__main__': block. According to the pytorch official website recommendation, I think it would be better if fastai didn’t return CUDA tensors in multi-process loading because of these kinds of subtleties.