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
Advertisement
Answer
BCELoss()
expects float labels. Yours are int8 (aka char). Converting them to float in the last line of__getitem__()
should fix the issue.