Learn.fit() throws TypeError

Hello everyone,

I am trying to follow the example in the data_block section of the Documentation (link related to object detection.

I ran the following lines of code:

coco = untar_data(URLs.COCO_TINY)
images, lbl_bbox = get_annotations(coco/‘train.json’)
img2bbox = dict(zip(images, lbl_bbox))
get_y_func = lambda o:img2bbox[o.name]

data = (ObjectItemList.from_folder(coco)
.split_by_rand_pct()
.label_from_func(get_y_func)
.transform(get_transforms(), tfm_y=True)
.databunch(bs=16, collate_fn=bb_pad_collate))

Then I want to do a basic fitting:

learn = cnn_learner(data, models.resnet18, metrics=accuracy)
learn.fit(1)

I get the following error and stack trace:

<ipython-input-30-8587f3539821> in <module>
----> 1 learn.fit(1)

~\.conda\envs\gputest\lib\site-packages\fastai\basic_train.py in fit(self, epochs, lr, wd, callbacks)
    200         callbacks = [cb(self) for cb in self.callback_fns + listify(defaults.extra_callback_fns)] + listify(callbacks)
    201         self.cb_fns_registered = True
--> 202         fit(epochs, self, metrics=self.metrics, callbacks=self.callbacks+callbacks)
    203 
    204     def create_opt(self, lr:Floats, wd:Floats=0.)->None:

~\.conda\envs\gputest\lib\site-packages\fastai\basic_train.py in fit(epochs, learn, callbacks, metrics)
     99             for xb,yb in progress_bar(learn.data.train_dl, parent=pbar):
    100                 xb, yb = cb_handler.on_batch_begin(xb, yb)
--> 101                 loss = loss_batch(learn.model, xb, yb, learn.loss_func, learn.opt, cb_handler)
    102                 if cb_handler.on_batch_end(loss): break
    103 

~\.conda\envs\gputest\lib\site-packages\fastai\basic_train.py in loss_batch(model, xb, yb, loss_func, opt, cb_handler)
     28 
     29     if not loss_func: return to_detach(out), yb[0].detach()
---> 30     loss = loss_func(out, *yb)
     31 
     32     if opt is not None:

TypeError: __call__() takes 3 positional arguments but 4 were given

I tried on a bigger dataset of my own, and I get the same results. What seems to be the problem? Thank you all for your help! :slight_smile:

I’m pretty sure you cannot do object detection with a cnn_learner, but I can’t be sure as your stack trace is impossible to read. Please use code blocks using:
```python
your code or stack trace here
```
And clean your stack trace, I don’t know why it contains tons of ``` and *, which makes it very hard to read.
Something like this would be far easier (this stack trace is totally unrelated btw, just for the example):

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-125-fc18b9150d2d> in <module>
----> 1 merge_doubles(SUB_PATH/'merge_test.csv', SUB_PATH/'merge_test.csv')

<ipython-input-19-3afd8b49d48b> in merge_doubles(old, new)
      5         new_rle = ''
      6         for rle in df.loc[df['ImageId']==id, 'EncodedPixels']:
----> 7             new_rle = merge_rles(new_rle, rle)
      8         new_df.loc[k] = [id, new_rle]
      9     new_df.to_csv(new, index=False)

<ipython-input-124-427711b938f8> in merge_rles(rle1, rle2)
      5     rle = []
      6     pixels1 = relat2absol(rle1).split()
----> 7     pixels2 = relat2absol(rle2).split()
      8     while i1<len(pixels1) and i2<len(pixels2):
      9         p1 = int(pixels1[i1])

<ipython-input-123-1faa12e90390> in relat2absol(rle)
      1 def relat2absol(rle):
      2     if str(rle) == '-1': return '-1'
----> 3     pixels = rle.split()
      4     new_rle = []
      5     cur = 0

AttributeError: 'float' object has no attribute 'split'

I formatted the stack trace now. Thanks!

Very nice, thanks ! What does learner.loss_func yield ? And learner.data.one_batch[1] ? And learner.model(learner.data.one_batch[0]) ?
Again, I think your model won’t work well with the object detection task.

learner.loss_func returns FlattenedLoss of BCEWithLogitsLoss()
learner.data.one_batch[1] throwsTypeError: 'method' object is not subscriptable
learner.model(learner.data.one_batch[0]) throws the same TypeError: 'method' object is not subscriptable

I am a novice of fastai and Deep Learning in general, so maybe I’m missing some vital processing steps.

Oh yeah i gave you wrong commands so it can’t work: learner.data.one_batch()[1] and learner.model(learner.data.one_batch()[0]).

learner.data.one_batch()[1] returns

          [ 0.2182,  0.6468,  1.0000,  1.0000]],
 
         [[ 0.0000,  0.0000,  0.0000,  0.0000],
          [ 0.5723,  0.0628,  1.0000,  1.0000]],
 
         [[ 0.0000,  0.0000,  0.0000,  0.0000],
          [-1.0000, -1.0000,  0.0912,  1.0000]],
 
         [[ 0.0000,  0.0000,  0.0000,  0.0000],
          [-1.0000, -1.0000, -0.3958, -0.2999]],
 
         [[-1.0000, -0.5155,  0.2903,  1.0000],
          [ 0.5509,  0.2951,  1.0000,  1.0000]],
 
         [[ 0.0000,  0.0000,  0.0000,  0.0000],
          [ 0.9808, -1.0000,  1.0000, -0.0547]],
 
         [[-1.0000,  0.5567, -0.5639,  1.0000],
          [-0.4107, -0.0384,  1.0000,  1.0000]],
 
         [[ 0.0000,  0.0000,  0.0000,  0.0000],
          [-0.5588, -1.0000,  1.0000, -0.2692]],
 
         [[-0.0313,  0.1240,  1.0000,  0.8897],
          [-0.7950,  0.8813, -0.5438,  0.9500]],
 
         [[ 0.0000,  0.0000,  0.0000,  0.0000],
          [-0.9246, -0.9551,  1.0000,  1.0000]],
 
         [[ 0.0000,  0.0000,  0.0000,  0.0000],
          [-1.0000,  0.4600, -0.7774,  1.0000]],
 
         [[ 0.0000,  0.0000,  0.0000,  0.0000],
          [-0.1822, -1.0000,  1.0000, -0.0156]]

and

learner.model(learner.data.one_batch()[0]) throws what seems to be a CUDA error:

<ipython-input-20-59740219ab07> in <module>
----> 1 learner.model(learner.data.one_batch()[0])

~\.conda\envs\gputest\lib\site-packages\torch\nn\modules\module.py in __call__(self, *input, **kwargs)
    487             result = self._slow_forward(*input, **kwargs)
    488         else:
--> 489             result = self.forward(*input, **kwargs)
    490         for hook in self._forward_hooks.values():
    491             hook_result = hook(self, input, result)

~\.conda\envs\gputest\lib\site-packages\torch\nn\modules\container.py in forward(self, input)
     90     def forward(self, input):
     91         for module in self._modules.values():
---> 92             input = module(input)
     93         return input
     94 

~\.conda\envs\gputest\lib\site-packages\torch\nn\modules\module.py in __call__(self, *input, **kwargs)
    487             result = self._slow_forward(*input, **kwargs)
    488         else:
--> 489             result = self.forward(*input, **kwargs)
    490         for hook in self._forward_hooks.values():
    491             hook_result = hook(self, input, result)

~\.conda\envs\gputest\lib\site-packages\torch\nn\modules\container.py in forward(self, input)
     90     def forward(self, input):
     91         for module in self._modules.values():
---> 92             input = module(input)
     93         return input
     94 

~\.conda\envs\gputest\lib\site-packages\torch\nn\modules\module.py in __call__(self, *input, **kwargs)
    487             result = self._slow_forward(*input, **kwargs)
    488         else:
--> 489             result = self.forward(*input, **kwargs)
    490         for hook in self._forward_hooks.values():
    491             hook_result = hook(self, input, result)

~\.conda\envs\gputest\lib\site-packages\torch\nn\modules\conv.py in forward(self, input)
    318     def forward(self, input):
    319         return F.conv2d(input, self.weight, self.bias, self.stride,
--> 320                         self.padding, self.dilation, self.groups)
    321 
    322 

RuntimeError: Expected object of backend CPU but got backend CUDA for argument #2 'weight'```

Oh yes the batch gets transferred to CPU, so the right command is learner.model(learner.data.one_batch(cpu=False)[0]).
But I don’t actually need it, your problem is that object detection returns a bunch of things (labels and bounding boxes) and require a special loss. The loss that you are using by default here is designed for binary segmentation or classification, and only expects one target, not 2 like here. Besides, cnn_learner is built to do classification, not object detection.
To be honest, if you are new to deep learning, you should start with classification problems, as object detection is quite harder and has no implemented model in fastai. If you really want to do object detection want to use an existing model, there are some coming from torchvision. But you’ll still need to create your own loss and understand how fastai handles bounding boxes well, which will take time. A good order to apprehend computer vision and fastai library would be classification > semantic segmentation > object detection/instance segmentation.