Dblock.dataloaders() - TypeError: 'L' object is not callable

Goal: create a model using FastAI’s DataBlock().

I want to create a DataBrick() based on documentation.

I think ‘L’ object refers to fastcore.foundation.L type.

How can I fix this?

Error occurs on:

return dblock.dataloaders()
import glob
from pathlib import Path

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

def _label_func():
    return glob.glob('yasmine-sftp/Slides/*.svs.geojson')


def load(root: Path) -> DataBlock:
    batch_tfms = [aug_transforms(max_lighting=0.2),
                  aug_transforms(max_rotate=90),
                  aug_transforms(max_rotate=90, max_lighting=0.2),
                  aug_transforms(max_rotate=180),
                  aug_transforms(max_rotate=180, max_lighting=0.2),
                  aug_transforms(max_rotate=270),
                  aug_transforms(max_rotate=270, max_lighting=0.2)]

    dblock = DataBlock(get_items=get_image_files(str(root), recurse=True),
                       splitter=RandomSplitter(seed=42),
                       get_y=Pipeline(_label_func()),
                       batch_tfms=batch_tfms)  # <fastai.data.block.DataBlock object at 0x7fb91d79a400>

    return dblock.dataloaders(root, bs=16)

ROOT = Path('images/')  # Detection Folder
load(ROOT)

Traceback:

  File "/home/daniel/PycharmProjects/project/load_data.py", line 26, in <module>
    dblock.dataloaders(root, bs=16)  # <fastai.data.block.DataBlock object at 0x7fb91d79a400>
  File "/home/daniel/miniconda3/envs/venv/lib/python3.6/site-packages/fastai/data/block.py", line 113, in dataloaders
    dsets = self.datasets(source, verbose=verbose)
  File "/home/daniel/miniconda3/envs/venv/lib/python3.6/site-packages/fastai/data/block.py", line 107, in datasets
    items = (self.get_items or noop)(source) ; pv(f"Found {len(items)} items", verbose)
TypeError: 'L' object is not callable

Okay the Traceback error provides us with enough information to figure out what’s going on.

What it’s saying is that it expects self.get_items to be a callable (like a function), since it is followed by (source) which is the input to the callable. But instead self.get_items is an L, which as you correctly noted, is a fastcore class.

In your code, you have get_items=get_image_files(str(root), recurse=True), which actually goes ahead and gets the image file paths and puts it into an L object. So to solve your error, you just pass in get_image_files, or if you really need recurse=True, you could do partial(get_image_files, recurse=True). root will anyway be passed to the self.get_items function as we can see in the Traceback error, which is where the confusion and error arises from.

Hope this helps!

3 Likes

Hi @miwojc, I saw your answer here saying “With augmentation the number of training images doesn’t change,” which aligned with the understanding I’d gained from the Part 1 course I just completed, but the way @DanielBell99 lines up seven aug_transforms above confused me to wonder whether it increased the number of image presented. I’m now clear on that, but still left wondering what practical benefit there is in apply seven transforms like that. I’d naively think that two transforms like this…

     batch_tfms = [
                 aug_transforms(max_rotate=90, max_lighting=0.2),
                 aug_transforms(max_rotate=270, max_lighting=0.2)]

would be no different from a single transform…

     batch_tfms = [
                 aug_transforms(max_rotate=360, max_lighting=0.4),]

I never chained Aug transforms like that. It would be an interesting experiment to try i think.