AttributeError: 'NoneType' object has no attribute 'take'

I want to train an object detector based on the Train a salad detector with TensorFlow Lite Model Maker notebook, but I’m using a dataset in Pascal VOC format.

The dataset can be loaded with

dataloader = object_detector.DataLoader.from_pascal_voc('chess-detection/images', 'chess-detection/annotations', ['white-rook', 'white-knight', 'white-bishop', 'white-king', 'white-queen', 'white-pawn', 'black-rook', 'black-knight', 'black-bishop', 'black-king', 'black-queen', 'black-pawn'])

but when trying to split it into a training and validation set using the split method (train_data, validation_data = dataloader.split(0.8)) im getting the following error:

AttributeError Traceback (most recent call last)

[<ipython-input-21-337838b38d0a>](https://localhost:8080/#) in <module>() ----> 1 train_data, validation_data = dataloader.split(0.8)

1 frames

[/usr/local/lib/python3.7/dist-packages/tensorflow_examples/lite/model_maker/core/data_util/dataloader.py](https://localhost:8080/#) in _split(self, fraction, *args) 145 146 train_size = int(self._size * fraction) --> 147 trainset = self.__class__(ds.take(train_size), train_size, *args) 148 149 test_size = self._size - train_size

AttributeError: 'NoneType' object has no attribute 'take'

Any help is greatly appreciated.

1 Like

Hi @Gi_T
Have you checked version of TensorFlow? Is it 2.5.0? Can you try with this version?

1 Like

Just checked. The Tensorflow version used is 2.5.0.

1 Like

Have you followed all the instructions here ?
It seems that they have an example inside from towardsscience.

1 Like

Yes, I think so. I already managed to train an object detector on my Microcontroller detection dataset. Both these datasets were labeled using LabelImg. The only differences between the two are that the microcontroller dataset is already split into a training and validation/test folder.

But strangely, if I train a model with the dataset loaded with:

dataloader = object_detector.DataLoader.from_pascal_voc('chess-detection/images', 'chess-detection/annotations', ['white-rook', 'white-knight', 'white-bishop', 'white-king', 'white-queen', 'white-pawn', 'black-rook', 'black-knight', 'black-bishop', 'black-king', 'black-queen', 'black-pawn'])

it seems to work. I’m only receiving the error when trying to split the dataset with the split method.

1 Like

If I were in your position I would split the data myself then…and raise an issue at the github page here

2 Likes

Okay. Thanks for the help

1 Like

If anybody is interested I split the data with the following code:

# split data into training and testing set
import os, random, shutil

os.mkdir('chess-detection/train')
os.mkdir('chess-detection/test')

image_paths = os.listdir('chess-detection/images')
random.shuffle(image_paths)

for i, image_path in enumerate(image_paths):
  if i < int(len(image_paths) * 0.8):
    shutil.copy(f'chess-detection/images/{image_path}', 'chess-detection/train')
    shutil.copy(f'chess-detection/annotations/{image_path.replace("JPG", "xml")}', 'chess-detection/train')
  else:
    shutil.copy(f'chess-detection/images/{image_path}', 'chess-detection/test')
    shutil.copy(f'chess-detection/annotations/{image_path.replace("JPG", "xml")}', 'chess-detection/test')

Also @George_Soloupis it seems like you can’t create any issues in the tensorflow/examples repository.

1 Like

@Gi_T I will forward the thread to the TensorFlow Lite team and if I have a response I will get back to you.

1 Like

Thanks a lot @George_Soloupis

1 Like

@Gi_T Dataloader for object detection doesn’t support split for now. We will add an error message if users call the split function first to avoid misleading. We will consider adding this function later.

As for now, If you’d like to split the data into train_data and valdation_data, you need to set annotation_filenames parameter in the from_pascal_voc function (api) to specify which annotation files to be used. For instance, if you have annotation files: 1.xml, 2.xml, 3.xml. You can use

train_dataloader = object_detector.DataLoader.from_pascal_voc(..., annotation_filenames=['1', '2'])
validation_dataloader = object_detector.DataLoader.from_pascal_voc(..., annotation_filenames=['3'])
3 Likes