'RuntimeError: Expected object of scalar type Long but got scalar type Float for argument #2 'target'
I'm running into an issue while calculating the loss for my Neural Net. I'm not sure why the program expects a long object because all my Tensors are in float form. I looked at threads with similar errors and the solution was to cast Tensors as floats instead of longs, but that wouldn't work in my case because all my data is already in float form when passed to the network.
Here's my code:
# Dataloader
from torch.utils.data import Dataset, DataLoader
class LoadInfo(Dataset):
def __init__(self, prediction, indicator):
self.prediction = prediction
self.indicator = indicator
def __len__(self):
return len(self.prediction)
def __getitem__(self, idx):
data = torch.tensor(self.indicator.iloc[idx, :],dtype=torch.float)
data = torch.unsqueeze(data, 0)
label = torch.tensor(self.prediction.iloc[idx, :],dtype=torch.float)
sample = {'data': data, 'label': label}
return sample
# Trainloader
test_train = LoadInfo(train_label, train_indicators)
trainloader = DataLoader(test_train, batch_size=64,shuffle=True, num_workers=1,pin_memory=True)
# The Network
class NetDense2(nn.Module):
def __init__(self):
super(NetDense2, self).__init__()
self.rnn1 = nn.RNN(11, 100, 3)
self.rnn2 = nn.RNN(100, 500, 3)
self.fc1 = nn.Linear(500, 100)
self.fc2 = nn.Linear(100, 20)
self.fc3 = nn.Linear(20, 3)
def forward(self, x):
x1, h1 = self.rnn1(x)
x2, h2 = self.rnn2(x1)
x = F.relu(self.fc1(x2))
x = F.relu(self.fc2(x))
x = self.fc3(x)
return x
# Allocate / Transfer to GPU
dense2 = NetDense2()
dense2.cuda()
# Optimizer
import torch.optim as optim
criterion = nn.CrossEntropyLoss() # specify the loss function
optimizer = optim.SGD(dense2.parameters(), lr=0.001, momentum=0.9,weight_decay=0.001)
# Training
dense2.train()
loss_memory = []
for epoch in range(50): # loop over the dataset multiple times
running_loss = 0.0
for i, samp in enumerate(trainloader):
# get the inputs
ins = samp['data']
targets = samp['label']
tmp = []
tmp = torch.squeeze(targets.float())
ins, targets = ins.cuda(), tmp.cuda()
# zero the parameter gradients
optimizer.zero_grad()
# forward + backward + optimize
outputs = dense2(ins)
loss = criterion(outputs, targets) # The loss
loss.backward()
optimizer.step()
# keep track of loss
running_loss += loss.data.item()
I get the error from above in the line " loss = criterion(outputs, targets) "
Solution 1:[1]
As per the documentation and official example at pytorch webpage, The targets passed to nn.CrossEntropyLoss() should be in torch.long format
# official example
import torch
import torch.nn as nn
loss = nn.CrossEntropyLoss()
input = torch.randn(3, 5, requires_grad=True)
target = torch.empty(3, dtype=torch.long).random_(5)
# if you will replace the dtype=torch.float, you will get error
output = loss(input, target)
output.backward()
update this line in your code as
label = torch.tensor(self.prediction.iloc[idx, :],dtype=torch.long) #updated torch.float to torch.long
Solution 2:[2]
Small workaround to your code would be something like this:
for epoch in range(50): # loop over the dataset multiple times
running_loss = 0.0
for i, samp in enumerate(trainloader):
# get the inputs
ins = samp['data']
targets = samp['label'].long() # HERE IS THE CHANGE <<---------------
tmp = []
tmp = torch.squeeze(targets.float())
ins, targets = ins.cuda(), tmp.cuda()
# zero the parameter gradients
optimizer.zero_grad()
# forward + backward + optimize
outputs = dense2(ins)
loss = criterion(outputs, targets) # The loss
loss.backward()
optimizer.step()
# keep track of loss
running_loss += loss.data.item()
Solution 3:[3]
A simple fix which worked for me by replacing
loss = criterion(outputs, targets)
with
loss = criterion(outputs, targets.long())
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Mughees |
| Solution 2 | Prajot Kuvalekar |
| Solution 3 | homelessmathaddict |
