0

I am using PyTorch in my program(Binary Classification).

The output from my model and actual labels are

model outputs are: (tensor([[0.4512],
        [0.2273],
        [0.4710],
        [0.2965]], grad_fn=<SigmoidBackward0>), torch.float32), 
actuall labels are (tensor([[0],
        [1],
        [0],
        [1]], dtype=torch.int8), torch.int8)

When I calculate the Binary Cross Entropy, it gives me the error

RuntimeError: Found dtype Char but expected Float

I have no idea how it is finding the Char dtype.

Even If calculate it manually, it gives me this error.

import torch
cri = torch.nn.BCELoss()
cri(torch.tensor([[0.4470],[0.5032],[0.3494],[0.5057]], dtype=torch.float), torch.tensor([[0],[1],[0],[0]], dtype=torch.int8))

My DataLoader is

# CREATING DATA LOADER

class MyDataset(torch.utils.data.Dataset):
    def __init__(self, dataframe, subset='train'):
        self.subset = subset
        
        self.dataframe = dataframe
        self.transforms = transforms.Compose([
                                        transforms.RandomResizedCrop(224),
                                        transforms.RandomHorizontalFlip(),
                                        transforms.Grayscale(),
                                        transforms.ToTensor(),
                                        transforms.Normalize((0.5), (0.5))
                                    ])
        
    
    def __len__(self):
        return len(self.dataframe)

    def __getitem__(self, index):
        row = self.dataframe.iloc[index]
        img = Image.open(os.path.join('/kaggle/input/mura-v11',row['path']))
        
        if self.subset=='train':
#             print(torch.tensor(0, dtype=torch.int8) if row['labels'] == 'negative' else torch.tensor(1, dtype=torch.int8))
            return (self.transforms(img), torch.tensor(0, dtype=torch.int8) if row['labels'] == 'negative' else torch.tensor(1, dtype=torch.int8))
        else:
            tensor_img = torchvision.transforms.functional.to_tensor(img)
            return (tensor_img, torch.tensor(0, dtype=torch.int8) if row['labels'] == 'negative' else torch.tensor(1, dtype=torch.int8))

my training loop is

def train_model(model, criterion, optimizer, scheduler, num_epochs=25):
    since = time.time()

    best_model_wts = copy.deepcopy(model.state_dict())
    best_acc = 0.0

    for epoch in range(num_epochs):
        print(f'Epoch {epoch}/{num_epochs - 1}')
        print('-' * 10)

        # Each epoch has a training and validation phase
        for phase in ['train', 'val']:
            if phase == 'train':
                model.train()  # Set model to training mode
            else:
                model.eval()   # Set model to evaluate mode

            running_loss = 0.0
            running_corrects = 0

            # Iterate over data.
            for inputs, labels in dataloaders[phase]:
                inputs = inputs.to(device)
                labels = labels.to(device)

                # zero the parameter gradients
                optimizer.zero_grad()

                # forward
                # track history if only in train
                with torch.set_grad_enabled(phase == 'train'):
                    outputs = model(inputs)
                    _, preds = torch.max(outputs, 1)
                    print(f"model outputs are: {outputs, outputs.dtype}, \nmodel labels are {labels.view(labels.shape[0],1), labels.dtype}")
                    loss = criterion(outputs, labels.view(labels.shape[0], 1))

                    # backward + optimize only if in training phase
                    if phase == 'train':
                        loss.backward()
                        optimizer.step()

                # statistics
                running_loss += loss.item() * inputs.size(0)
                running_corrects += torch.sum(preds == labels.data)
            if phase == 'train':
                scheduler.step()

            epoch_loss = running_loss / dataset_sizes[phase]
            epoch_acc = running_corrects.double() / dataset_sizes[phase]

            print(f'{phase} Loss: {epoch_loss:.4f} Acc: {epoch_acc:.4f}')

            # deep copy the model
            if phase == 'val' and epoch_acc > best_acc:
                best_acc = epoch_acc
                best_model_wts = copy.deepcopy(model.state_dict())

        print()

    time_elapsed = time.time() - since
    print(f'Training complete in {time_elapsed // 60:.0f}m {time_elapsed % 60:.0f}s')
    print(f'Best val Acc: {best_acc:4f}')

    # load best model weights
    model.load_state_dict(best_model_wts)
    return model

And my Model is

class MuraModel(torch.nn.Module):
    def __init__(self):
        """
        In the constructor we instantiate four parameters and assign them as
        member parameters.
        """
        super().__init__()
        self.inp = torch.nn.Conv2d(1, 3, 3) # Change the num of channels to 3
        self.backbone = models.resnet18(pretrained=True)
        num_ftrs = self.backbone.fc.in_features
        self.backbone.fc = nn.Linear(num_ftrs, 1)
        self.act = nn.Sigmoid()

    def forward(self, x):
        """
        In the forward function we accept a Tensor of input data and we must return
        a Tensor of output data. We can use Modules defined in the constructor as
        well as arbitrary operators on Tensors.
        """
        three_channel = self.inp(x)
        back_out = self.backbone(three_channel)
        return self.act(back_out)



# inp = nn.Conv2d(1, 3, 3)
# model_ft = models.resnet18(pretrained=True)(inp)
# num_ftrs = model_ft.fc.in_features
# model_ft.fc = nn.Linear(num_ftrs, 2)

# model_ft = model_ft.to(device)




criterion = nn.BCELoss()
model = MuraModel()

optimizer_ft = optim.SGD(model.parameters(), lr=0.001, momentum=0.9)

# Decay LR by a factor of 0.1 every 7 epochs
exp_lr_scheduler = lr_scheduler.StepLR(optimizer_ft, step_size=7, gamma=0.1)

model = train_model(model, criterion, optimizer_ft, exp_lr_scheduler,
                       num_epochs=25)

How to overcome it.

EDIT

Trace back on train_model function:

---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
/tmp/ipykernel_17/2718774237.py in <module>
      1 model = train_model(model, criterion, optimizer_ft, exp_lr_scheduler,
----> 2                        num_epochs=25)

/tmp/ipykernel_17/2670448577.py in train_model(model, criterion, optimizer, scheduler, num_epochs)
     33                     _, preds = torch.max(outputs, 1)
     34                     print(f"model outputs are: {outputs, outputs.dtype}, \nmodel labels are {labels.view(labels.shape[0],1), labels.dtype}")
---> 35                     loss = criterion(outputs, labels.view(labels.shape[0], 1))
     36 
     37                     # backward + optimize only if in training phase

/opt/conda/lib/python3.7/site-packages/torch/nn/modules/module.py in _call_impl(self, *input, **kwargs)
   1108         if not (self._backward_hooks or self._forward_hooks or self._forward_pre_hooks or _global_backward_hooks
   1109                 or _global_forward_hooks or _global_forward_pre_hooks):
-> 1110             return forward_call(*input, **kwargs)
   1111         # Do not call functions when jit is used
   1112         full_backward_hooks, non_full_backward_hooks = [], []

/opt/conda/lib/python3.7/site-packages/torch/nn/modules/loss.py in forward(self, input, target)
    610 
    611     def forward(self, input: Tensor, target: Tensor) -> Tensor:
--> 612         return F.binary_cross_entropy(input, target, weight=self.weight, reduction=self.reduction)
    613 
    614 

/opt/conda/lib/python3.7/site-packages/torch/nn/functional.py in binary_cross_entropy(input, target, weight, size_average, reduce, reduction)
   3063         weight = weight.expand(new_size)
   3064 
-> 3065     return torch._C._nn.binary_cross_entropy(input, target, weight, reduction_enum)
   3066 
   3067 
RuntimeError: Found dtype Char but expected Float


Trace back on calculating loss individually

---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
/tmp/ipykernel_17/4156819471.py in <module>
      1 import torch
      2 cri = torch.nn.BCELoss()
----> 3 cri(torch.tensor([[0.4470],[0.5032],[0.3494],[0.5057]], dtype=torch.float), torch.tensor([[0],[1],[0],[0]], dtype=torch.int8))

/opt/conda/lib/python3.7/site-packages/torch/nn/modules/module.py in _call_impl(self, *input, **kwargs)
   1108         if not (self._backward_hooks or self._forward_hooks or self._forward_pre_hooks or _global_backward_hooks
   1109                 or _global_forward_hooks or _global_forward_pre_hooks):
-> 1110             return forward_call(*input, **kwargs)
   1111         # Do not call functions when jit is used
   1112         full_backward_hooks, non_full_backward_hooks = [], []

/opt/conda/lib/python3.7/site-packages/torch/nn/modules/loss.py in forward(self, input, target)
    610 
    611     def forward(self, input: Tensor, target: Tensor) -> Tensor:
--> 612         return F.binary_cross_entropy(input, target, weight=self.weight, reduction=self.reduction)
    613 
    614 

/opt/conda/lib/python3.7/site-packages/torch/nn/functional.py in binary_cross_entropy(input, target, weight, size_average, reduce, reduction)
   3063         weight = weight.expand(new_size)
   3064 
-> 3065     return torch._C._nn.binary_cross_entropy(input, target, weight, reduction_enum)
   3066 
   3067 

RuntimeError: Found dtype Char but expected Float
5
  • Hi, could you provide a sample of your data? Also, please specify the second error that occurs when you manually calculate the entropy. Commented Aug 2, 2022 at 7:12
  • @Imad I am using Mura Dataset. The error message is similar for both. If you want i can paste the full traceback. Commented Aug 2, 2022 at 9:00
  • always put FULL error message (starting at word "Traceback") in question (not in comments) as text (not screenshot, not link to external portal). There are other useful information in the full error/traceback. Commented Aug 2, 2022 at 9:56
  • error suggests that you have string instead of float value in some column. Maybe you have some value as string. Commented Aug 2, 2022 at 9:59
  • @furas I have added the traceback. You can calculate the standalone BCELoss as I did. There is no string. Commented Aug 2, 2022 at 10:16

1 Answer 1

2

BCELoss() expects float labels. Yours are int8 (aka char). Converting them to float in the last line of__getitem__()should fix the issue.

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you. This works. Don't you think it is misleading to call int as char?
Also if the predicted labels are float32, and yours are float16, it still does not work.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.