Nike
Nike

Reputation: 29

Expected object of scalar type Long but got scalar type Int for argument #2 in loss function

I have encountered the following error:

 RuntimeError                              Traceback (most recent call last)
    <ipython-input-42-276f5444b449> in <module>
    ----> 1 train_epocs(model, optimizer, train_dl, valid_dl, epochs=15)
    
    <ipython-input-39-6f4616cc5f25> in train_epocs(model, optimizer, train_dl, val_dl, epochs, C)
         11             y_bb = y_bb.cuda().float()
         12             out_class, out_bb = model(x)
    ---> 13             loss_class = F.cross_entropy(out_class, y_class, reduction="sum")
         14             loss_bb = F.l1_loss(out_bb, y_bb, reduction="none").sum(1)
         15             loss_bb = loss_bb.sum()
    
    ~\anaconda3\lib\site-packages\torch\nn\functional.py in cross_entropy(input, target, weight, size_average, ignore_index, reduce, reduction)
       2822     if size_average is not None or reduce is not None:
       2823         reduction = _Reduction.legacy_get_string(size_average, reduce)
    -> 2824     return torch._C._nn.cross_entropy_loss(input, target, weight, _Reduction.get_enum(reduction), ignore_index)
       2825 
       2826 
    
    RuntimeError: Expected object of scalar type Long but got scalar type Int for argument #2 'target' in call to _thnn_nll_loss_forward

I have been training the network with the following set-up. We have 26 classes. The code is adopted from https://jovian.ai/ranerajesh/road-signs-bounding-box-prediction/v/10 I have my own custom dataset that has been structured in a way required for this code to run. However, I have encountered a RunTime error.

    def normalize(im):
        """Normalizes images with Imagenet stats."""
        imagenet_stats = np.array([[0.485, 0.456, 0.406], [0.229, 0.224, 0.225]])
        return (im - imagenet_stats[0])/imagenet_stats[1]

    class RoadDataset(Dataset):
        def __init__(self, paths, bb, y, transforms=False):
            self.transforms = transforms
            self.paths = paths.values
            self.bb = bb.values
            self.y = y.values
        def __len__(self):
            return len(self.paths)
        
        def __getitem__(self, idx):
            path = self.paths[idx]
            print(path)
            y_class = self.y[idx]
            x, y_bb = transformsXY(path, self.bb[idx], self.transforms)
            x = normalize(x)
            x = np.rollaxis(x, 2)
            return x, y_class, y_bb
train_ds = RoadDataset(X_train['new_path'],X_train['new_bb'] ,y_train, transforms=True)
valid_ds = RoadDataset(X_val['new_path'],X_val['new_bb'],y_val)
batch_size = 2
train_dl = DataLoader(train_ds, batch_size=batch_size, shuffle=True)
valid_dl = DataLoader(valid_ds, batch_size=batch_size)

class BB_model(nn.Module):
    def __init__(self):
        super(BB_model, self).__init__()
        resnet = models.resnet34(pretrained=True)
        layers = list(resnet.children())[:8]
        self.features1 = nn.Sequential(*layers[:6])
        self.features2 = nn.Sequential(*layers[6:])
        self.classifier = nn.Sequential(nn.BatchNorm1d(512), nn.Linear(512, 26))
        self.bb = nn.Sequential(nn.BatchNorm1d(512), nn.Linear(512, 26))
        
    def forward(self, x):
        x = self.features1(x)
        x = self.features2(x)
        x = F.relu(x)
        x = nn.AdaptiveAvgPool2d((1,1))(x)
        x = x.view(x.shape[0], -1)
        return self.classifier(x), self.bb(x)

def update_optimizer(optimizer, lr):
    for i, param_group in enumerate(optimizer.param_groups):
        param_group["lr"] = lr


def train_epocs(model, optimizer, train_dl, val_dl, epochs=10,C=1000):
    idx = 0
    for i in range(epochs):
        model.train()
        total = 0
        sum_loss = 0
        for x, y_class, y_bb in train_dl:
            batch = y_class.shape[0]
            x = x.cuda().float()
            y_class = y_class.cuda()
            y_bb = y_bb.cuda().float()
            out_class, out_bb = model(x)
            loss_class = F.cross_entropy(out_class, y_class, reduction="sum")
            loss_bb = F.l1_loss(out_bb, y_bb, reduction="none").sum(1)
            loss_bb = loss_bb.sum()
            loss = loss_class + loss_bb/C
            optimizer.zero_grad()
            loss.backward()
            optimizer.step()
            idx += 1
            total += batch
            sum_loss += loss.item()
        train_loss = sum_loss/total
        val_loss, val_acc = val_metrics(model, valid_dl, C)
        print("train_loss %.3f val_loss %.3f val_acc %.3f" % (train_loss, val_loss, val_acc))
    return sum_loss/total



def val_metrics(model, valid_dl, C=1000):
    model.eval()
    total = 0
    sum_loss = 0
    correct = 0 
    for x, y_class, y_bb in valid_dl:
        batch = y_class.shape[0]
        x = x.cuda().float()
        y_class = y_class.cuda()
        y_bb = y_bb.cuda().float()
        out_class, out_bb = model(x)
        loss_class = F.cross_entropy(out_class, y_class, reduction="sum")
        loss_bb = F.l1_loss(out_bb, y_bb, reduction="none").sum(1)
        loss_bb = loss_bb.sum()
        loss = loss_class + loss_bb/C
        _, pred = torch.max(out_class, 1)
        correct += pred.eq(y_class).sum().item()
        sum_loss += loss.item()
        total += batch
    return sum_loss/total, correct/total


model = BB_model().cuda()
parameters = filter(lambda p: p.requires_grad, model.parameters())
optimizer = torch.optim.Adam(parameters, lr=0.006)


train_epocs(model, optimizer, train_dl, valid_dl, epochs=15)

Upvotes: 1

Views: 204

Answers (1)

yakhyo
yakhyo

Reputation: 1656

loss_class = F.cross_entropy(out_class, y_class, reduction="sum")

In the line above, y_class is target of your out_class (for model predictions). The output from model is Long and your y_class has a Float type. So you need to change y_class's type to Long by:

y_class = y_class.long()
loss_class = F.cross_entropy(out_class, y_class, reduction="sum")

Upvotes: 1

Related Questions