Help debugging load and infer with the Siamese model

Hello, I am looking for help in loading and running inference with the Siamese model. I created a siamese model as described in this tutorial: fastai - Custom new task - siamese. I moved the SiameseImage class to a Python file so I could import it from both the training notebook and the inference notebook. Everything worked and looked fine. Then I save the model with the following code:

import dill
learn.export('siam_catsvdogs_tutorial.pkl', pickle_module=dill)

Then I loaded the model and an input image and visualized it with the following code:

from fastai.vision.all import *
import dill

learner = load_learner('siam_catsvdogs_tutorial.pkl', cpu=False, pickle_module=dill)

path = untar_data(URLs.PETS)
files = get_image_files(path/"images")

from siam_utils import SiameseImage
# I moved SiameseImage to a file because if I copied and pasted the code I would get the following error
# AssertionError: Expected an input of type in 
# - <class 'pathlib.PosixPath'>
# - <class '__main__.SiameseImage'>
#  but got <class '__main__.SiameseImage'>

imgtest = PILImage.create(files[0])
imgval = PILImage.create(files[100])
siamtest = SiameseImage(imgval, imgtest)

siamtest.show();

When I run that everything seems to work and it displays an image like I would expect. Then when I copy the siampredict patch from the tutorial, I get an error when I run it.

@patch
def siampredict(self:Learner, item, rm_type_tfms=None, with_input=False):
    res = self.predict(item, rm_type_tfms=None, with_input=False)
    if res[0] == tensor(0):
        SiameseImage(item[0], item[1], 'Prediction: Not similar').show()
    else:
        SiameseImage(item[0], item[1], 'Prediction: Similar').show()
    return res

res = learn.siampredict(siamtest)

Here’s the error (note my line numbers might be different, but that’s just due to a formatter):

Unexpected exception formatting exception. Falling back to standard exception
Traceback (most recent call last):
  File "/home/julius/miniconda3/envs/pt2/lib/python3.10/site-packages/IPython/core/interactiveshell.py", line 3378, in run_code
    exec(code_obj, self.user_global_ns, self.user_ns)
  File "/tmp/ipykernel_23558/1905235485.py", line 1, in <module>
    res = learner.siampredict(siamtest)
  File "/tmp/ipykernel_23558/1808791625.py", line 3, in siampredict
    res = self.predict(item, rm_type_tfms=None, with_input=False)
  File "/home/julius/miniconda3/envs/pt2/lib/python3.10/site-packages/fastai/learner.py", line 450, in predict
    inp, preds, _, dec_preds = self.get_preds(dl=dl, with_input=True, with_decoded=True)
  File "/home/julius/miniconda3/envs/pt2/lib/python3.10/site-packages/fastai/learner.py", line 434, in get_preds
    self._do_epoch_validate(dl=dl)
  File "/home/julius/miniconda3/envs/pt2/lib/python3.10/site-packages/fastai/learner.py", line 352, in _do_epoch_validate
    self._with_events(self.all_batches, "validate", CancelValidException)
  File "/home/julius/miniconda3/envs/pt2/lib/python3.10/site-packages/fastai/learner.py", line 298, in _with_events
    f()
  File "/home/julius/miniconda3/envs/pt2/lib/python3.10/site-packages/fastai/learner.py", line 306, in all_batches
    for o in enumerate(self.dl):
  File "/home/julius/miniconda3/envs/pt2/lib/python3.10/site-packages/fastai/data/load.py", line 129, in __iter__
    for b in _loaders[self.fake_l.num_workers==0](self.fake_l):
  File "/home/julius/miniconda3/envs/pt2/lib/python3.10/site-packages/torch/utils/data/dataloader.py", line 681, in __next__
    data = self._next_data()
  File "/home/julius/miniconda3/envs/pt2/lib/python3.10/site-packages/torch/utils/data/dataloader.py", line 721, in _next_data
    data = self._dataset_fetcher.fetch(index)  # may raise StopIteration
  File "/home/julius/miniconda3/envs/pt2/lib/python3.10/site-packages/torch/utils/data/_utils/fetch.py", line 39, in fetch
    data = next(self.dataset_iter)
  File "/home/julius/miniconda3/envs/pt2/lib/python3.10/site-packages/fastai/data/load.py", line 140, in create_batches
    yield from map(self.do_batch, self.chunkify(res))
  File "/home/julius/miniconda3/envs/pt2/lib/python3.10/site-packages/fastcore/basics.py", line 230, in chunked
    res = list(itertools.islice(it, chunk_sz))
  File "/home/julius/miniconda3/envs/pt2/lib/python3.10/site-packages/fastai/data/load.py", line 155, in do_item
    try: return self.after_item(self.create_item(s))
  File "/home/julius/miniconda3/envs/pt2/lib/python3.10/site-packages/fastcore/transform.py", line 299, in __call__
    return compose_tfms(o, tfms=self.fs, split_idx=self.split_idx)
  File "/home/julius/miniconda3/envs/pt2/lib/python3.10/site-packages/fastcore/transform.py", line 234, in compose_tfms
    x = f(x, **kwargs)
  File "/home/julius/miniconda3/envs/pt2/lib/python3.10/site-packages/fastai/vision/augment.py", line 48, in __call__
    self.before_call(b, split_idx=split_idx)
  File "/home/julius/miniconda3/envs/pt/lib/python3.8/site-packages/fastai/vision/augment.py", line -1, in before_call
AttributeError: 'int' object has no attribute 'random'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/julius/miniconda3/envs/pt2/lib/python3.10/site-packages/IPython/core/interactiveshell.py", line 1997, in showtraceback
    stb = self.InteractiveTB.structured_traceback(
  File "/home/julius/miniconda3/envs/pt2/lib/python3.10/site-packages/IPython/core/ultratb.py", line 1112, in structured_traceback
    return FormattedTB.structured_traceback(
  File "/home/julius/miniconda3/envs/pt2/lib/python3.10/site-packages/IPython/core/ultratb.py", line 1006, in structured_traceback
    return VerboseTB.structured_traceback(
  File "/home/julius/miniconda3/envs/pt2/lib/python3.10/site-packages/IPython/core/ultratb.py", line 859, in structured_traceback
    formatted_exception = self.format_exception_as_a_whole(etype, evalue, etb, number_of_lines_of_context,
  File "/home/julius/miniconda3/envs/pt2/lib/python3.10/site-packages/IPython/core/ultratb.py", line 812, in format_exception_as_a_whole
    frames.append(self.format_record(r))
  File "/home/julius/miniconda3/envs/pt2/lib/python3.10/site-packages/IPython/core/ultratb.py", line 730, in format_record
    result += ''.join(_format_traceback_lines(frame_info.lines, Colors, self.has_colors, lvals))
  File "/home/julius/miniconda3/envs/pt2/lib/python3.10/site-packages/stack_data/utils.py", line 145, in cached_property_wrapper
    value = obj.__dict__[self.func.__name__] = self.func(obj)
  File "/home/julius/miniconda3/envs/pt2/lib/python3.10/site-packages/stack_data/core.py", line 734, in lines
    pieces = self.included_pieces
  File "/home/julius/miniconda3/envs/pt2/lib/python3.10/site-packages/stack_data/utils.py", line 145, in cached_property_wrapper
    value = obj.__dict__[self.func.__name__] = self.func(obj)
  File "/home/julius/miniconda3/envs/pt2/lib/python3.10/site-packages/stack_data/core.py", line 681, in included_pieces
    pos = scope_pieces.index(self.executing_piece)
  File "/home/julius/miniconda3/envs/pt2/lib/python3.10/site-packages/stack_data/utils.py", line 145, in cached_property_wrapper
    value = obj.__dict__[self.func.__name__] = self.func(obj)
  File "/home/julius/miniconda3/envs/pt2/lib/python3.10/site-packages/stack_data/core.py", line 660, in executing_piece
    return only(
  File "/home/julius/miniconda3/envs/pt2/lib/python3.10/site-packages/executing/executing.py", line 167, in only
    raise NotOneValueFound('Expected one value, found 0')
executing.executing.NotOneValueFound: Expected one value, found 0

I’m able to run inference in the same notebook that I trained the model, but for some reason I’m not when I load it. Does anyone have any ideas why?

One layer of the debugging onion …

import random appears to be missing.

Thanks for the suggestion. I tried that and it didn’t work. Also, it appears that from fastai.vision.all import * contains random because I can use it. It looks to me that in this case an int is being passed where the code was expecting a Python object with a random attribute, not that the top level random module is missing. But I still haven’t figured out what the issue is.

Hi Julius,

Can you check if within your code, you’ve used a variablename which is there in the namespace of any of fastai’s source code?

Just as an example if I do

import random
x = random.randint(10)
random = 10
y = random.randint(10)

The last line wouldn’t execute because random is now an int.

So if similarly if you used a variablename which is an object which is supposed to have a random attribute and accidentally initialize it to an int, then such an error could arise.

I don’t know if that is the case, just wanted to cite a possibility…

Hope this helps!

Regards,
Vinayak.

Hi Vinayak,

Thanks for the suggestion - it’s an interesting idea. I don’t think this is what is happening because I used all the same variable names that are used in the tutorial. The most likely culprits in my load script are path and files, but these are used throughout fastai documents and tutorials as well. And I didn’t set any variables to be ints. So I don’t think this is the cause but I appreciate you bringing up the possibility.

1 Like

Hey Julius,

Could you share your siam_utils.py file? That would also help debug better :slight_smile: !

Regards,
Vinayak

Sure! Here’s the full text of siam_utils.py:

from fastai.vision.all import *

class SiameseImage(fastuple):
    def show(self, ctx=None, **kwargs): 
        if len(self) > 2:
            img1,img2,similarity = self
        else:
            img1,img2 = self
            similarity = 'Undetermined'
        if not isinstance(img1, Tensor):
            if img2.size != img1.size: img2 = img2.resize(img1.size)
            t1,t2 = tensor(img1),tensor(img2)
            t1,t2 = t1.permute(2,0,1),t2.permute(2,0,1)
        else: t1,t2 = img1,img2
        line = t1.new_zeros(t1.shape[0], t1.shape[1], 10)
        return show_image(torch.cat([t1,line,t2], dim=2), title=similarity, ctx=ctx, **kwargs)

Hi Julius,

Are you doing training and inference on the same OS or different OSes?

Does this thread help?

Thanks,
Vinayak.

It’s all on Linux.

What’s confusing is that there is an error on line -1, how to make any sense of it really? Can you try going into fastai.vision.augment.py and check if everything in your local environment is the same as what’s on the github repo here?

Regards,
Vinayak.

1 Like

I think I see a potential problem - those lines reference two different conda environments. It looks like it was trained on Python 3.8 and is being loaded with Python 3.10. I’ll check to see if that’s the issue.

1 Like

OK. I had to throw a lot more in siam_utils.py, but I was eventually able to get the above code to work when I ran everything with Python 3.10. I had to make some changes to the training code though.

I’d still be interested in the canonical solution though. Moving all my functions and classes into a separate file seems clunky. Does anyone know a better way?