sealpuppy
sealpuppy

Reputation: 633

Pytorch - TypeError: 'torch.Size' object cannot be interpreted as an integer

Hi I am training a PyTorch model and occurred this error:

----> 5 for i, data in enumerate(trainloader, 0):

TypeError: 'torch.Size' object cannot be interpreted as an integer

Not sure what this error means.

You can find my code here :

model.train()
for epoch in range(10):
    running_loss = 0

    for i, data in enumerate(trainloader, 0):

        inputs, labels = data

        optimizer.zero_grad()

        outputs = model(inputs)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()

        if i % 2000 == 0:
          print (loss.item())
        running_loss += loss.item()
        if i % 1000 == 0:
            print ('[%d, %5d] loss: %.3f' % (epoch, i, running_loss/ 1000))
            running_loss = 0

torch.save(model, 'FeatureNet.pkl')

Update

This is the codeblock for DataLoader. I am using a customized dataloader and datasets, which x are pictures with size (1025, 16) and y are one-hot encoded vectors for classification.

x_train.shape = (1100, 1025, 16)

y_train.shape = (1100, 10)

clean_dir = '/home/tk/Documents/clean/' 
mix_dir = '/home/tk/Documents/mix/' 
clean_label_dir = '/home/tk/Documents/clean_labels/' 
mix_label_dir = '/home/tk/Documents/mix_labels/' 

class MSourceDataSet(Dataset):

    def __init__(self, clean_dir, mix_dir, clean_label_dir, mix_label_dir):

        with open(clean_dir + 'clean0.json') as f:
            clean0 = torch.Tensor(json.load(f))

        with open(mix_dir + 'mix0.json') as f:
            mix0 = torch.Tensor(json.load(f))

        with open(clean_label_dir + 'clean_label0.json') as f:
            clean_label0 = torch.Tensor(json.load(f))


        with open(mix_label_dir + 'mix_label0.json') as f:
            mix_label0 = torch.Tensor(json.load(f))


        self.spec = torch.cat([clean0, mix0], 0)
        self.label = torch.cat([clean_label0, mix_label0], 0)

    def __len__(self):
        return self.spec.shape


    def __getitem__(self, index): 

        spec = self.spec[index]
        label = self.label[index]
        return spec, label

getitem

a, b = trainset.__getitem__(1000)
print (a.shape)
print (b.shape)

a.shape = torch.Size([1025, 16]); b.shape = torch.Size([10])

Error message

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-9-3bd71e5c00e1> in <module>()
      3     running_loss = 0
      4 
----> 5     for i, data in enumerate(trainloader, 0):
      6 
      7         inputs, labels = data

~/anaconda3/lib/python3.7/site-packages/torch/utils/data/dataloader.py in __next__(self)
    311     def __next__(self):
    312         if self.num_workers == 0:  # same-process loading
--> 313             indices = next(self.sample_iter)  # may raise StopIteration
    314             batch = self.collate_fn([self.dataset[i] for i in indices])
    315             if self.pin_memory:

~/anaconda3/lib/python3.7/site-packages/torch/utils/data/sampler.py in __iter__(self)
    136     def __iter__(self):
    137         batch = []
--> 138         for idx in self.sampler:
    139             batch.append(idx)
    140             if len(batch) == self.batch_size:

~/anaconda3/lib/python3.7/site-packages/torch/utils/data/sampler.py in __iter__(self)
     32 
     33     def __iter__(self):
---> 34         return iter(range(len(self.data_source)))
     35 
     36     def __len__(self):

TypeError: 'torch.Size' object cannot be interpreted as an integer

Upvotes: 4

Views: 21172

Answers (1)

MBT
MBT

Reputation: 24099

Your problem is the __len__ function. You cannot use the shape as return value.

Here is an example for illustration:

import torch
class Foo:
    def __init__(self, data):
        self.data = data
    def __len__(self):
        return self.data.shape

myFoo = Foo(data=torch.rand(10, 20))
print(len(myFoo))

Will raise exactly the same error:

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-285-e97aace2f622> in <module>
      7 
      8 myFoo = Foo(data=torch.rand(10, 20))
----> 9 print(len(myFoo))

TypeError: 'torch.Size' object cannot be interpreted as an integer

Since shape represents a torch.Size tuple:

print(myFoo.data.shape)

Output:

torch.Size([10, 20])

So you have to decide which dimension you want to hand over to __len__, for example the first dimension:

import torch
class Foo:
    def __init__(self, data):
        self.data = data
    def __len__(self):
        return self.data.shape[0] # choosing first dimension for len

myFoo = Foo(data=torch.rand(10, 20))
print(len(myFoo))
# prints 10

Works fine and returns 10. Of course you can also choose any other dimension of your input, but you have to choose one.

So in your code of your MSourceDataSet you have to change your __len__ function to for example:

def __len__(self):
    return self.spec.shape[0] # as said of course you can also choose other dimensions

This should solve your problem.

Upvotes: 6

Related Questions