Lesson 1 - Non-beginner discussion

Haha, that would be one hell of a feat!

I guess that’s it, getting a general understanding of how the library is structured would helo a great deal!

I started off with that and found that quite cumbersome as well mainly because of the jumping around. Atm, I just open VS code and import the library and ctrl+t stuff I want to find. the major downside to this fast search is you lose the opportunity to build that general structure of the library.

1 Like

you don’t have to jump around when you use ?? . am i missing something here ?:slightly_smiling_face: @harish3110
even doc(...) should help :slight_smile:

So when I am looking at a top level api and want to know more about a sub function used in the docs of that, i’ll have to close that and then search for that sub-function in another cell, understand what’s happening there and then again get back to the one I was originally looking at.

But in VS code i found it easier to just keep them in different pages for quick reference or just use the shortcut to get back to what I was looking for in the start. (I believe that’s alt + left arrow on windows and its ctrl + - on mac).

Also looks like the f12 key can be clicked on to go to that specific function directly rather than again searching for it.

ah ok makes sense :slight_smile:

A similar question for tips on this:
Note that for transfer learning, progressive resizing may actually hurt performance. This would happen if your pretrained model was quite similar to your transfer learning task and dataset, and was trained on similar sized images, so the weights don't need to be changed much. In that case, training on smaller images may damage the pretrained weights.
`
Q: “similar sized images” is there a range that you suggest?

On the other hand, if the transfer learning task is going to be on images that are of different sizes, shapes, or style to those used in the pretraining tasks, progressive resizing will probably help. As always, the answer to "does it help?" is "try it!".
Does size and shape here mean the same thing ie width and height of the image?

here in the book: https://github.com/fastai/fastbook/blob/master/07_sizing_and_tta.ipynb

1 Like

Wow, fantastic bit there! Yes I’d presume width and height IE I could have an image of a shape 800,400 and 400,800 and they would be considered different (also since they use shape specifically, I’d assume they are probably also referencing .shape too in a sneaky way) - Though don’t quote me on that too hard, mostly just showing an example of how dimensions could be different

oh so size is ht*wd and shape is ht by wd right ?
.size and .shape return the ‘sameish’ thing just inverted though if i’m not wrong. haha and PIL has a size that returns shape :exploding_head:

This explains it kinda well I think, I know it gets confusing :slight_smile:

1 Like

The more you are on a steep zone (let’s say between a plateau and the mountain top), the more you can safely use a large LR (large steps at each iteration). Once you get on a plateau, though, you should start looking for smaller throughs, hence the LR reduction. A big step would make you miss the smaller throughs.
Note: the mountain/valley picture should be taken with a grain of salt, since 3d intuition does not always applies well in higher dimensions…

Yeah, I noticed that too, experimentally. Worse than that, it will often improve the accuracy over the (same) valid set, but your model will silently lose generalization power, and you won’t notice until deployment, unless you have a large (and statistically representative) test set.

2 Likes

I see, I didn’t know that. Thank you. That is a hard one to solve. I have to experiment with this :slightly_smiling_face:

1 Like

Adult tabular dataset: if you took the course before, you may have outdated dataset.

I came across an error that ‘salary’ is not an index in the data. It turned out my dataset was from Nov. 2018 and did not contain ‘salary’. So I deleted it from ~/.fastai/data and ran it again and it worked!

1 Like

this question is not really related to lesson one but I don’t want to start a new topic.

what’s the best way get the labels for the predictions got from learn.get_preds()? Is there something build in fastai?!

right now I’m doing this:
dl = learn.dls.test_dl(imgs)
preds,_,dec_preds = learn.get_preds(dl=dl, with_decoded=True)
lbl_preds = [learn.dls.vocab[p] for p in dec_preds]

I tried to understand the code used in learn.predict() - which returns the real labels - but I don’t really get what’s going on there… too many maps decodes tuplify and detuplifys for me :wink:

What’s the best practice for saving predictions per batch? I know there’s the save_preds method for learners, but to my knowledge it just gets the predictions of all items in your dataset/dataloader then you have to go through each prediction and save it to file one-by-one.

Look at the tail end of learn.predict()’s code, specifically at the decode_batch() function. It’ll wind up returning your original X (the image) and the now fully decoded y

For a code example, see the “fastai straight” section here:

1 Like

Dear all,

I update my own dataset in Paperspace

from fastai2.vision.all import *
path = "/notebooks/storage/course-v4/nbs/images/dataset"
def is_cube(x): return x[0].startswith("c")
dls = ImageDataLoaders.from_name_func(
    path, get_image_files(path), valid_pct=0.2, seed=42,
    label_func=is_cube, item_tfms=Resize(224))
learn = cnn_learner(dls, resnet34, metrics=error_rate)
learn.fine_tune(4)

image

In the dataset folder I have only 20 pictures in .jpg format
10 cat A and 10 in cat B

Any idea why it is all nan and the values are all wrong?

@Albertotono first thing to do when debugging this situation is look at your dataloaders. What are their lengths? (how many batches)? You can explore this via len(dls.train) and len(dls.valid). Now what I can tell you is your training dataloader has zero batches. Why? The batch size (by default) is 64 and you only have 20 images. As such we can only make one batch, and here it made a batch of validation data. If you truly only want to use that low amount of images you should bring your batch size to 2 to see some data in each dataloader. Also what Sylvain says about the dropped batch below :slight_smile:

1 Like

You have a default batch size of 64 and in the training set, the last batch is dropped if it doesn’t have batch_size elements. So you’re not training on anything.

To adjust the batch size, pass bs=... in ImageDataLoaders

2 Likes

@muellerzr @sgugger you are awesome, thank you so much.

image
with DataAugmentation

it seems that I am doing something wrong, probably 20 images it not enough.
probably we do not need a lot of data, but we need a good amount lol
image
I looked at SinGAN paper

I am trying to build the DataBlocks API for MNIST and trying to figure out why

path = untar_data(URLs.MNIST_TINY)
dblock = DataBlock(blocks=(ImageBlock, CategoryBlock), 
                   get_items=get_image_files, 
                   get_x=PILImage.create,
                   get_y=parent_label, 
                   splitter=GrandparentSplitter())

This API doesn’t work when I do dls=dblock.dataloaders(path) .

Here is the stack trace:

AttributeError                            Traceback (most recent call last)
<ipython-input-59-0353eb4f73af> in <module>
----> 1 dls = dblock.dataloaders(path)

~/repos/fastai2/fastai2/data/block.py in dataloaders(self, source, path, verbose, **kwargs)
     96 
     97     def dataloaders(self, source, path='.', verbose=False, **kwargs):
---> 98         dsets = self.datasets(source)
     99         kwargs = {**self.dls_kwargs, **kwargs, 'verbose': verbose}
    100         return dsets.dataloaders(path=path, after_item=self.item_tfms, after_batch=self.batch_tfms, **kwargs)

~/repos/fastai2/fastai2/data/block.py in datasets(self, source, verbose)
     93         splits = (self.splitter or RandomSplitter())(items)
     94         pv(f"{len(splits)} datasets of sizes {','.join([str(len(s)) for s in splits])}", verbose)
---> 95         return Datasets(items, tfms=self._combine_type_tfms(), splits=splits, dl_type=self.dl_type, n_inp=self.n_inp, verbose=verbose)
     96 
     97     def dataloaders(self, source, path='.', verbose=False, **kwargs):

~/repos/fastai2/fastai2/data/core.py in __init__(self, items, tfms, tls, n_inp, dl_type, **kwargs)
    272     def __init__(self, items=None, tfms=None, tls=None, n_inp=None, dl_type=None, **kwargs):
    273         super().__init__(dl_type=dl_type)
--> 274         self.tls = L(tls if tls else [TfmdLists(items, t, **kwargs) for t in L(ifnone(tfms,[None]))])
    275         self.n_inp = (1 if len(self.tls)==1 else len(self.tls)-1) if n_inp is None else n_inp
    276 

~/repos/fastai2/fastai2/data/core.py in <listcomp>(.0)
    272     def __init__(self, items=None, tfms=None, tls=None, n_inp=None, dl_type=None, **kwargs):
    273         super().__init__(dl_type=dl_type)
--> 274         self.tls = L(tls if tls else [TfmdLists(items, t, **kwargs) for t in L(ifnone(tfms,[None]))])
    275         self.n_inp = (1 if len(self.tls)==1 else len(self.tls)-1) if n_inp is None else n_inp
    276 

~/repos/fastai2/fastcore/fastcore/foundation.py in __call__(cls, x, *args, **kwargs)
     39             return x
     40 
---> 41         res = super().__call__(*((x,) + args), **kwargs)
     42         res._newchk = 0
     43         return res

~/repos/fastai2/fastai2/data/core.py in __init__(self, items, tfms, use_list, do_setup, split_idx, train_setup, splits, types, verbose)
    212         if do_setup:
    213             pv(f"Setting up {self.tfms}", verbose)
--> 214             self.setup(train_setup=train_setup)
    215 
    216     def _new(self, items, **kwargs): return super()._new(items, tfms=self.tfms, do_setup=False, types=self.types, **kwargs)

~/repos/fastai2/fastai2/data/core.py in setup(self, train_setup)
    232             for f in self.tfms.fs:
    233                 self.types.append(getattr(f, 'input_types', type(x)))
--> 234                 x = f(x)
    235             self.types.append(type(x))
    236         types = L(t if is_listy(t) else [t] for t in self.types).concat().unique()

~/repos/fastai2/fastcore/fastcore/transform.py in __call__(self, x, **kwargs)
     70     @property
     71     def name(self): return getattr(self, '_name', _get_name(self))
---> 72     def __call__(self, x, **kwargs): return self._call('encodes', x, **kwargs)
     73     def decode  (self, x, **kwargs): return self._call('decodes', x, **kwargs)
     74     def __repr__(self): return f'{self.name}: {self.encodes} {self.decodes}'

~/repos/fastai2/fastcore/fastcore/transform.py in _call(self, fn, x, split_idx, **kwargs)
     80     def _call(self, fn, x, split_idx=None, **kwargs):
     81         if split_idx!=self.split_idx and self.split_idx is not None: return x
---> 82         return self._do_call(getattr(self, fn), x, **kwargs)
     83 
     84     def _do_call(self, f, x, **kwargs):

~/repos/fastai2/fastcore/fastcore/transform.py in _do_call(self, f, x, **kwargs)
     84     def _do_call(self, f, x, **kwargs):
     85         if not _is_tuple(x):
---> 86             return x if f is None else retain_type(f(x, **kwargs), x, f.returns_none(x))
     87         res = tuple(self._do_call(f, x_, **kwargs) for x_ in x)
     88         return retain_type(res, x)

~/repos/fastai2/fastcore/fastcore/dispatch.py in __call__(self, *args, **kwargs)
     96         if not f: return args[0]
     97         if self.inst is not None: f = MethodType(f, self.inst)
---> 98         return f(*args, **kwargs)
     99 
    100     def __get__(self, inst, owner):

~/repos/fastai2/fastai2/vision/core.py in create(cls, fn, **kwargs)
     96         if isinstance(fn,ndarray): return cls(Image.fromarray(fn))
     97         if isinstance(fn,bytes): fn = io.BytesIO(fn)
---> 98         return cls(load_image(fn, **merge(cls._open_args, kwargs)))
     99 
    100     def show(self, ctx=None, **kwargs):

AttributeError: 'DataBlock' object has no attribute '_open_args'

Rather:

dblock = DataBlock(blocks=(ImageBlock, CategoryBlock), 
                   get_items=get_image_files, 
                   get_y=parent_label, 
                   splitter=GrandparentSplitter())

Works.