'tuple' object has no attribute 'trainer'

Hello,
I bump into this error while trying to train my network:

Traceback (most recent call last):
  File "TrainMain.py", line 229, in <module>
    trainer.fit(model, dataloader)
  File "/usr/local/lib/python3.8/dist-packages/pytorch_lightning-1.5.9-py3.8.egg/pytorch_lightning/trainer/trainer.py", line 740, in fit
    self._call_and_handle_interrupt(
  File "/usr/local/lib/python3.8/dist-packages/pytorch_lightning-1.5.9-py3.8.egg/pytorch_lightning/trainer/trainer.py", line 685, in _call_and_handle_interrupt
    return trainer_fn(*args, **kwargs)
  File "/usr/local/lib/python3.8/dist-packages/pytorch_lightning-1.5.9-py3.8.egg/pytorch_lightning/trainer/trainer.py", line 771, in _fit_impl
    self._data_connector.attach_data(
  File "/usr/local/lib/python3.8/dist-packages/pytorch_lightning-1.5.9-py3.8.egg/pytorch_lightning/trainer/connectors/data_connector.py", line 190, in attach_data
    self._copy_trainer_model_properties(model)
  File "/usr/local/lib/python3.8/dist-packages/pytorch_lightning-1.5.9-py3.8.egg/pytorch_lightning/trainer/connectors/data_connector.py", line 196, in _copy_trainer_model_properties
    m.trainer = proxy(self.trainer)
AttributeError: 'tuple' object has no attribute 'trainer'

This error seems to come from the data in the dataloader/dataset.
Here is the call in the TrainMain.py:

dataloader = MyDataLoader(train_dataset, [val_dataset0, val_dataset1], [test_dataset0, test_dataset1], d_params["doc_batch"], d_params["doc_height"])
trainer = pl.Trainer(
        accelerator=acc,
        devices=1,
        max_epochs=args.nb_epochs,
        precision=32,
        default_root_dir=f"Models/{net_name}",
        enable_progress_bar=True,
        logger=logger,
        gradient_clip_val=0.5,
        num_sanity_val_steps=0,
        callbacks=callbacks_fn,
        reload_dataloaders_every_n_epochs=0
    )
    trainer.fit(model, dataloader)

And my dataloader and dataset:

class Dataset:

    def __init__(self, database_name, augmenters=[], transforms=[], mode="train"):
        self.database_name = database_name
        self.augmenters = augmenters
        self.transforms = transforms
        
        self.mode = mode
        self.val_ratio = val_ratio

    
    def compose(self):
        with open("annots.json", "r", encoding="utf-8") as a:
            annots = json.load(a)

        doc_path = self._compose_ttv()
        doc_names = [self._get_doc_name(p) for p in doc_path]
        
        self.annots = {k:v for k,v in annots.items() if k in doc_names}
        self.samples = doc_path
        random.shuffle(self.samples)

    def _compose_ttv(self):
       # compose the dataset based on the mode ("train", "val", "test")

    def __len__(self):
        return len(self.samples)
    
    def __getitem__(self, idx):
        assert idx <= len(self), "index out of range"
       
        doc_path = self.samples[i]
        doc_name = self._get_doc_name(doc_path)
        o_annot = self.annots[doc_name]

        img = cv2.imread(doc_path, cv2.IMREAD_GRAYSCALE)

        for t in self.transforms:
            o_annot, model = t(o_annot, model, self.current_epoch)

        for aug in self.augmenters:
            img, o_annot = aug(img, o_annot)
                
        img = img.reshape(1, *img.shape)            
        img = img/255
        img = torch.from_numpy(img).to(dtype=self.dtype)
        return img, o_annot, doc_name 
class SimpleDataLoader(pl.LightningDataModule):

    def __init__(self, train_dataset, val_dataset, test_dataset, entities, batch_size=2, max_height=800):
        super(SimpleDataLoader, self).__init__()
        self.train_dataset = train_dataset
        self.val_dataset = val_dataset
        self.test_dataset = test_dataset
        self.batch_size = batch_size
        self.collate = Collate(max_height, entities)
    
    def train_dataloader(self):
        self.train_dataset.current_epoch = self.trainer.current_epoch
        return DataLoader(self.train_dataset, batch_size=self.batch_size, collate_fn=self.collate)
    
    def val_dataloader(self):
        return [DataLoader(self.val_dataset[i], batch_size=self.batch_size, collate_fn=self.collate) for i in range(len(self.val_dataset))]
    
    def test_dataloader(self):
        return [DataLoader(self.test_dataset[i], batch_size=self.batch_size, collate_fn=self.collate) for i in range(len(self.test_dataset))]
    
    def __post_init__(cls):
        super().__init__()

Do you have an idea of what may be the cause of the error or leads as to where investigate?
Thanks a lot.

Hi @timotheeneitthoffer

This error you posted is very strange:

    m.trainer = proxy(self.trainer)
AttributeError: 'tuple' object has no attribute 'trainer'

This would mean either m is a tuple or self. Both cases are weird.

Is it possible that you accidentally passed in a tuple of a model to the trainer.fit() method? You might have a typo like this:

model = MyModel(),  # <-- trailing comma makes this a tuple, oops?

This is just a wild guess.

Hi,
Thanks a lot, I had no idea where the error could come from as I did not modified my training file, but it seems that I misswrote the “,” at some point.

Thanks for pointing that out.

Have a nice day.

1 Like