AttributeError: 'function' object has no attribute 'fs'

Hi all,

I’m trying to apply what I learned in chapter 4.
Sofar, I have the following notebook.

However, when I run it, I get this error:

---------------------------------------------------------------------------

AttributeError                            Traceback (most recent call last)

<ipython-input-11-f9934caba1f5> in <module>()
     16 
     17 # how can the resnet18 automagically infer the number of output/categories to guess?
---> 18 learner = cnn_learner(dls, resnet18, opt_func=SGD, loss_func=nn.CrossEntropyLoss(), metrics=accuracy, lr=0.1)
     19 
     20 learner.fit(20)

1 frames

/usr/local/lib/python3.7/dist-packages/fastai/vision/learner.py in _add_norm(dls, meta, pretrained)
    155     stats = meta.get('stats')
    156     if stats is None: return
--> 157     if not dls.after_batch.fs.filter(risinstance(Normalize)):
    158         dls.add_tfms([Normalize.from_stats(*stats)],'after_batch')
    159 

AttributeError: 'function' object has no attribute 'fs'

What is the fs attribute and how can I add it to the dataloaders?

I’ve researched the documentation and it seems that fs is related to data augmentation. I could find the following sentence from here:

fs should be list-like, and contain a functions that will be composed together

Not sure what that mean as well :thinking:

Versions of fastai and fastcore?

I’m using fastai 1.0.61.

It does not seem that I’m using fastcore. I, at least, didn’t run the step to install it as mentioned here.

Try restarting your instance after the install. You’re looking for fastai v2

Not sure what “restarting the instance” refers to. The notebook is hosted on Google Colab (free membership) so unless I’m mistaken, I cannot restart the VM. I tried to restart the runtime many times (factory reset too), but it still installs fastai v1.

Not factory reset, restart runtime. It’s the option two above Factory Reset

Oh it works! Now I have fastai v2.

How restarting the runtime after having installed the package updates the package? I’m really confused :thinking:

It’s stored in the runtimes memory if you’ve tried running any cell before that, or sometimes colab just does that. It comes preinstalled with fastai v1, and we need to override it. Restarting it is the solution.

Thanks for the explanation.

So now I have fastai v2 but the error is still there.
Do I need to update anything in the DataLoaders?

I’m also having this issue, which wasn’t solved by restarting the runtime, but which I did find a workaround for.

Running fastai version 2.6.3. I’m setting up DataLoaders in almost exactly the same way as notebook #04, but I’m still getting the exact same missing attribute error as the OP:

/usr/local/lib/python3.7/dist-packages/fastai/vision/learner.py in _add_norm(dls, meta, pretrained)
    187     stats = meta.get('stats')
    188     if stats is None: return
--> 189     if not dls.after_batch.fs.filter(risinstance(Normalize)):
    190         dls.add_tfms([Normalize.from_stats(*stats)],'after_batch')
    191 

AttributeError: 'function' object has no attribute 'fs'

I solved the issue by passing a normalize=False argument to the vision_learner, as suggested in this thread: Get a DataLoaders from training and validation DataLoader - #5 by originof

But I have no idea why this works, since I’m still just dipping toes into ML here.

Looking at the code for the fastai function, this really seems like the kind of thing that shouldn’t be throwing errors if unspecified? Shouldn’t the default be not to normalize data if there isn’t enough information (i.e. no after_batch.fs) to do so?

I’d like to understand what’s going on here if anyone can explain.

Here’s my code:

train_xs = [None] * 10
train_ys = [None] * 10
for i in range(train_xs):
  filenames = (path/'training'/str(i)).ls().sorted()
  tensors = [tensor(Image.open(o)) for o in filenames]
  train_xs[i] = torch.stack(tensors).float()/255
  train_ys[i] = tensor([i] * len(filenames)).unsqueeze(1)

train_xs = torch.cat(train_xs).view(-1, 28*28)
train_ys = torch.cat(train_ys)
train_dset = list(zip(train_xs, train_ys))

(similar code to create valid_dset)

train_dl = DataLoader(train_dset, batch_size=4, shuffle=True)
valid_dl = DataLoader(valid_dset, batch_size=4, shuffle=True)
dls = DataLoaders(train_dl, valid_dl)
dls.c = 10 # define number of categories to avoid runtime error

learn = vision_learner(dls, models.resnet18, loss_func=CrossEntropyLossFlat())