AttributeError: 'str' object has no attribute 'cuda'

Viewed 51

I am trying to move my data to GPU by doing this

batch["img"] = [img.cuda() for img in batch["img"]]
batch["label"] = [label.cuda() for label in batch["label"]]

However, i get this error for the labels for OCR

AttributeError: 'str' object has no attribute 'cuda'

I also tried .to('cuda') and similar error.

More details are as follows. This is the pytorch Dataset class

class SynthDataset(Dataset):
    def __init__(self, opt):
        super(SynthDataset, self).__init__()
        self.path = os.path.join(opt['path'], opt['imgdir'])
        self.images = os.listdir(self.path)
        self.nSamples = len(self.images)
        f = lambda x: os.path.join(self.path, x)
        self.imagepaths = list(map(f, self.images))
        transform_list =  [transforms.Grayscale(1),
                            transforms.ToTensor(), 
                            transforms.Normalize((0.5,), (0.5,))]
        self.transform = transforms.Compose(transform_list)
        self.collate_fn = SynthCollator()
    def __len__(self):
        return self.nSamples

    def __getitem__(self, index):
        assert index <= len(self), 'index range error'
        imagepath = self.imagepaths[index]

        imagefile = os.path.basename(imagepath)
        img = Image.open(imagepath)
        if self.transform is not None:
            img = self.transform(img)
        item = {'img': img, 'idx':index}
        item['label'] = imagefile.split('_')[0]
        return item 

As you can see the generator outputs a dictionary with image and labels where the labels is the text contained in the image

1 Answers

Yo !

If I get your code right, your are building your custom dataset to output an image and its label. Your label comes from the first part of your image filename, so it is a string, as stated in the error message. Your object needs to be a Torch tensor to be moved on the GPU with .cuda().

If you want to keep your code as is, you need to transform your label into a vector form. I suspect your labels to be stuff like "cat", "dog", etc The usual way to transform labels into numerical forms are one-hot-encoding, or simply map each label to an integer. There is abundant resources about it on the web. Then you can turn your label into a Tensor object and move it to the GPU.

However, I would highly recommand to change the way you build your tensor dataset. You are calling .cuda() on every image tensor in your list. When forwarding a neural network, you batch your data into a tensor (for instance stacking your images into a new dimension), then call .cuda() on the whole batch tensor. Same thing for the labels. Check the Pytorch documentation as there is probably the exact example you are looking for (a custom dataset with an image and its label).

Good luck !

Related