I am writing this Image Classifier and I have defined the loaders but getting this mistake and I have no clue about it.
I have defined the train loader, for a better explanation I tried this
for ina,lab in train_loader:
print(type(ina))
print(type(lab))
and I got
<class 'torch.Tensor'>
<class 'tuple'>
Now, For training of the model, I did
def train_model(model,optimizer,n_epochs,criterion):
start_time = time.time()
for epoch in range(1,n_epochs-1):
epoch_time = time.time()
epoch_loss = 0
correct = 0
total = 0
print( "Epoch {}/{}".format(epoch,n_epochs))
model.train()
for inputs,labels in train_loader:
inputs = inputs.to(device)
labels = labels.to(device)
optimizer.zero_grad()
output = model(inputs)
loss = criterion(output,labels)
loss.backward()
optimizer.step()
epoch_loss +=loss.item()
_,pred =torch.max(output,1)
correct += (pred.cpu()==label.cpu()).sum().item()
total +=labels.shape[0]
acc = correct/total
and I got the error:
Epoch 1/15
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-36-fea243b3636a> in <module>
----> 1 train_model(model=arch, optimizer=optim, n_epochs=15, criterion=criterion)
<ipython-input-34-b53149a4bac0> in train_model(model, optimizer, n_epochs, criterion)
12 for inputs,labels in train_loader:
13 inputs = inputs.to(device)
---> 14 labels = labels.to(device)
15 optimizer.zero_grad()
16 output = model(inputs)
AttributeError: 'tuple' object has no attribute 'to'
If you want anything more, please tell me! Thanks
Edit: The label looks like this. This was an Image Classification between Bee and Wasp. It also contains insects and non insects
('wasp', 'wasp', 'insect', 'insect', 'wasp', 'insect', 'insect', 'wasp', 'wasp', 'bee', 'insect', 'insect', 'other', 'bee', 'other', 'wasp', 'other', 'wasp', 'bee', 'bee', 'wasp', 'wasp', 'wasp', 'wasp', 'bee', 'wasp', 'wasp', 'other', 'bee', 'wasp', 'bee', 'bee') ('wasp', 'wasp', 'insect', 'bee', 'other', 'wasp', 'insect', 'wasp', 'insect', 'insect', 'insect', 'wasp', 'wasp', 'insect', 'wasp', 'wasp', 'wasp', 'bee', 'wasp', 'wasp', 'insect', 'insect', 'wasp', 'wasp', 'bee', 'wasp', 'insect', 'bee', 'bee', 'insect', 'insect', 'other')
It literally means that the the tuple class in Python doesn't have a method called to
. Since you're trying to put your labels onto your device, just do labels = torch.tensor(labels).to(device)
.
If you don't want to do this, you can change the way the DataLoader works by making it return your labels as a PyTorch tensor rather than a tuple.
Since the labels seem to be strings, I would convert them to one-hot encoded vectors first:
>>> import torch
>>> labels_unique = set(labels)
>>> keys = {key: value for key, value in zip(labels_unique, range(len(labels_unique)))}
>>> labels_onehot = torch.zeros(size=(len(labels), len(keys)))
>>> for idx, label in enumerate(labels_onehot):
... labels_onehot[idx][keys[label]] = 1
...
>>> labels_onehot = labels.to(device)
I'm shooting a bit in the dark here because I don't know the details exactly, but yeah strings won't work with tensors.