RuntimeError: Input type (unsigned char) and bias type (float) should be the same

Geoffrey_Payne: <p>The error message appears clear enough but I do not understand why I am getting it or how to fix it.<br>
My code is as follows;</p>
<pre><code class="lang-auto">for epoch in range(hyper.epochs):
    epoch_loss = 0
    epoch_accuracy = 0
    
    for data, label in train_loader:
        data = data.to(gpu.device)
        label = label.to(gpu.device)
        
        output = model(data)
</code></pre>
<p>The error is from the last line above.<br>
The model is defined as</p>
<pre><code class="lang-auto">import torch.nn as nn
# Input Layer: It represent input image data. 
# Conv Layer: This layer will extract features from image.
# Pooling Layer: This layer reduces the spatial volume of input image after convolution.
# Fully Connected Layer: It connect the network from a layer to another layer
# Output Layer: It is the predicted values layer. 
class Cnn(nn.Module):
    def __init__(self):
        super(Cnn, self).__init__()
        
        self.layer1 = nn.Sequential(
            nn.Conv2d(3, 16, kernel_size=3, padding=0, stride=2),
            nn.BatchNorm2d(16),
            nn.ReLU(),
            nn.MaxPool2d(2)
        )
        
        self.layer2 = nn.Sequential(
            nn.Conv2d(16,32, kernel_size=3, padding=0, stride=2),
            nn.BatchNorm2d(32),
            nn.ReLU(),
            nn.MaxPool2d(2)
            )
        
        self.layer3 = nn.Sequential(
            nn.Conv2d(32,64, kernel_size=3, padding=0, stride=2),
            nn.BatchNorm2d(64),
            nn.ReLU(),
            nn.MaxPool2d(2)
        )
        self.fc1 = nn.Linear(3*3*64,10)
        self.dropout = nn.Dropout(0.5)
        self.fc2 = nn.Linear(10,2)
        self.relu = nn.ReLU()
        
        
    def forward(self,x):
        out = self.layer1(x)
        out = self.layer2(out)
        out = self.layer3(out)
        out = out.view(out.size(0),-1)
        out = self.relu(self.fc1(out))
        out = self.fc2(out)
        return out
</code></pre>
<p>the error is on the line; out = self.layer1(x)<br>
The dataloader is reading in images;</p>
<pre><code class="lang-auto">import torch
from torch.utils.data import Dataset
from torchvision import transforms
from PIL import Image
from pathlib import Path

class dataset(Dataset):
    def __init__(self, image_paths, dict_classes, logging):
        self.image_paths = image_paths
        self.dict_classes = dict_classes
        self.logging = logging
        
    #dataset length
    def __len__(self):
        return len(self.image_paths)
  
    #load an one of images
    def __getitem__(self, idx):
        img_path = self.image_paths[idx]
        img = Image.open(img_path)
        transform = transforms.Compose([
            transforms.PILToTensor(),
            transforms.Resize((256, 256)),
            transforms.RandomResizedCrop(256)
        ])
        img_tensor = transform(img)
        _key = Path(img_path).parts[3]  
        label = self.dict_classes[_key]
        return img_tensor, label
</code></pre>

ptrblck: <p>Based on the error message it seems as if the input tensor use the <code>uint8</code> <code>dtype</code> while the model uses the expected <code>float32</code> <code>dtype</code>. Note that <code>PILToTensor</code> will keep the same <code>dtype</code> of the input image which is most likely causing the issue. Use <code>ToTensor()</code> to normalize the input image and return it in <code>float32</code> format, which should fix the error.</p>

FabianAmherd: <aside class="quote no-group quote-modified" data-username="ptrblck" data-post="2" data-topic="170957">
<div class="title">
<div class="quote-controls"></div>
<img loading="lazy" alt="" width="24" height="24" src="https://discuss.pytorch.org/user_avatar/discuss.pytorch.org/ptrblck/48/1823_2.png" class="avatar"> ptrblck:</div>
<blockquote>
<p>… Use <code>ToTensor()</code> to normalize the input image and return it in <code>float32</code> format, which should fix the error.</p>
</blockquote>
</aside>
<p>Also, make sure to either create the transformation object first before calling the function from the quoted answer, or you could use the functional API by doing <code>import torchvision.transforms.functional as TF</code> and then calling <code>TF.to_tensor(image)</code></p>

Oliver: <p>Hi,</p>
<p>I have the same error after I tried switching torchvision transforms totensor to using albumentations, before I had been using albumentations for augmentations and torchvision transforms for <code>ToTensor</code> which is the commented out code blow, that worked fine, but this doesn’t anymore and returns the error in the title.</p>
<pre><code class="lang-auto">class ImageDataset(Dataset):
    def __init__(self, paths, aug, size):
        self.paths = paths 
        # self.transformer = Transform()
        # self.mask_transform = Mask_Transform()
        self.aug = aug
        self.size = size
        
    
    def __getitem__(self, idx: int):
        image_path, mask_path = self.paths[idx]
        image = cv2.imread(image_path, -1)[:, :, :3]
        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
        mask = cv2.imread(mask_path, 0) 
        mask = np.where(mask &gt; 0, 1.0, 0) #I originally called this last, switched to see if that was the error
        t = self.aug(image = image, mask = mask)
        image = t['image']
        mask = t['mask']
        
        # image = self.transformer(image) # only called torchvision totensor
        # mask = self.mask_transform(mask) #only called torchvision totensor
        return image, mask
    
    def __len__(self):
        return self.size    
    
    
train_transforms = A.Compose([
                A.HorizontalFlip(p=0.5),
                A.VerticalFlip(p=0.5),
                A.RandomRotate90(p=0.5),
                A.RandomBrightness(limit = 0.1, p = 0.5),  
                A.CLAHE(p=0.2),
                A.RandomBrightnessContrast(p=0.2),    
                A.RandomGamma(p=0.2),
                ToTensorV2()
                ])
</code></pre>
<p>Is there something that is wrong here?<br>
Despite all examples doing the contrary, there is an excepted answer at stackoverflow that said to switch ToTensorV2() to the front, I tried that and still get the same error in the title.</p>
<p>Many thanks in advance, as to why I am trying to switch to albumentations, I want to make it more uniform, and 2nd I also am still debugging the <code>eval</code> <code>train</code> thing <img src="https://discuss.pytorch.org/images/emoji/apple/sweat_smile.png?v=12" title=":sweat_smile:" class="emoji" alt=":sweat_smile:" loading="lazy" width="20" height="20"></p>

ptrblck: <p>Based on the <a href="https://github.com/albumentations-team/albumentations/blob/9b0525f479509195a7a7b7c19311d8e63bbc6494/albumentations/pytorch/transforms.py#L60-L104">source code</a> of <code>ToTensorV2</code> I guess this error is expected since no <code>dtype</code> transformations are applied to the input tensors (unless I miss them). <code>ToTensorV2</code> seems to only transpose the image if needed and convert it to a tensor.</p>

Oliver: <p>Thank you! Hmm, does that mean that I should call <code>.float()</code> on the images after?</p>

ptrblck: <p>I’m not deeply familiar with <code>albumentations</code> so don’t know what their standard workflow is, but using your code I get an image output in <code>torch.uint8</code> with values in <code>[0, 255]</code>, so you might want to normalize the tensor additionally.</p>

Oliver: <p>I see, thank you very much! The docs said the old <code>ToTensor</code> does divide by 255.0 and I was wondering if they just didn’t write it for brevity. Thanks again!</p>

holly: <p>I struggled with this problem and this discussion got me <em>almost</em> all the way to the solution (thanks!). While digging through the Albumentations docs I found out that they have a <a href="https://github.com/albumentations-team/albumentations/blob/e3b47b3a127f92541cfeb16abbb44a6f8bf79cc8/albumentations/augmentations/transforms.py#L1591" rel="noopener nofollow ugc">“ToFloat()” transform</a> that you can string onto the end of your <code>A.Compose()</code> transformations. Adding that line changed my tensors from dtype uint8 to float32 and resolved the type discrepancy that was preventing me from running my autoencoder. So for example, this works:</p>
<pre><code class="lang-auto">train_transforms = A.Compose(
    [
        A.Flip(p=0.1),
        A.GridDistortion(p=0.05),
        A.ToFloat(),
        ToTensorV2()
    ]
)
</code></pre>
<p>if you want to apply no transformations aside from converting your images to float tensors, this works for that purpose:</p>
<pre><code class="lang-auto">train_transforms = A.Compose(
    [
        A.ToFloat(),
        ToTensorV2()
    ]
)
</code></pre>

apachetechnology: <p>Please correct my code. I tried solution suggested in this post but I could not resolve the issue.</p>
<pre><code class="lang-auto">import os
import pandas as pd

from torchvision.io import read_image
from torch.utils.data import Dataset
import torchvision.transforms.functional as TF

#--------------------------------------------------------------------------------------
# torch.utils.data.Dataset is an abstract class representing a dataset. 
# A custom dataset should inherit Dataset and override the following methods:
# __len__ so that len(dataset) returns the size of the dataset.
#__getitem__ to support the indexing such that dataset[i] can be used to get ith sample.
#------------------------------    --------------------------------------------------------
    class CustomImageDataset(Dataset):
        def __init__(self, annotations_file, img_dir, 
                     transform=None, target_transform=None):
            self.dfAnnotations = pd.read_csv(annotations_file)
            self.img_dir = img_dir
            self.transform = transform
            self.target_transform = target_transform
    
        def __len__(self):
            return len(self.dfAnnotations)
    
        def __getitem__(self, idx):
            img_path = os.path.join(self.img_dir, 
                                    self.dfAnnotations.iloc[idx, 0])
            image = read_image(img_path)
            #image = TF.to_tensor(image)
            #image = io.imread(img_path)
            label = self.dfAnnotations.iloc[idx, 1]
    
            if self.transform:
                image = self.transform(image)
    
            if self.target_transform:
                label = self.target_transform(label)
    
            return image, label
</code></pre>
<pre><code class="lang-auto">        dsTrain = CustomImageDataset(strAnnotationTrain, strDataPath)
        dsTest = CustomImageDataset(strAnnotationTest, strDataPath)
        print('Train=', len(dsTrain), 'Test=', len(dsTest))

        self.mDLTrain = DataLoader(dsTrain, batch_size=nTrainSz,
                                 shuffle=True, pin_memory=True, 
                                 num_workers=min(multiprocessing.cpu_count(),4))
        self.mDLTest = DataLoader(dsTest, batch_size=1,
                                 shuffle=False, num_workers=4)

        test_batches = enumerate(self.mDLTest)

        # Load single batch
        batch_idx, (images, labels) = next(test_batches)
        print(images.shape, labels.shape)
        self.ShowImg(images[0], str(labels[0]))
</code></pre>
<p>The output is:</p>
<p>torch.Size([1, 3, 256, 256]) torch.Size([1])<br>
The images is correctly plotted.</p>
<p>However, when I train the image using a basic CNN</p>
<pre><code class="lang-auto">class cnn_4layer(nn.Module):
    def __init__(self, in_ch, in_dim, width=2, linear_size=256):
        super(cnn_4layer, self).__init__()
        self.conv1 = nn.Conv2d(in_ch, 4 * width, 4, stride=2, padding=1)
        self.conv2 = nn.Conv2d(4 * width, 8 * width, 4, stride=2, padding=1)
        self.fc1 = nn.Linear(8 * width * (in_dim // 4) * (in_dim // 4), linear_size)
        self.fc2 = nn.Linear(linear_size, 10)

    # Computes output Tensors from input Tensors
    def forward(self, x):
        x = F.relu(self.conv1(x))
        x = F.relu(self.conv2(x))
        x = torch.flatten(x, 1)
        x = F.relu(self.fc1(x))
        x = self.fc2(x)
        return x

# Model is initialized as
self.mModel = models.Models['cnn_4layer'](in_ch=3, in_dim=256)
</code></pre>
<pre><code class="lang-auto">The model will be running on cpu device
----------------------------------------------------------------
        Layer (type)               Output Shape         Param # 
================================================================
            Conv2d-1          [-1, 8, 128, 128]             392 
            Conv2d-2           [-1, 16, 64, 64]           2,064 
            Linear-3                  [-1, 256]      16,777,472 
            Linear-4                   [-1, 10]           2,570
================================================================
Total params: 16,782,498
Trainable params: 16,782,498
Non-trainable params: 0
----------------------------------------------------------------
Input size (MB): 0.75
Forward/backward pass size (MB): 1.50
Params size (MB): 64.02
Estimated Total Size (MB): 66.27
----------------------------------------------------------------
</code></pre>
<p>ERROR:</p>
<p><strong>return F.conv2d(input, weight, bias, self.stride,</strong><br>
<strong>RuntimeError: Input type (unsigned char) and bias type (float) should be the same</strong></p>
<p>STACKTRACE:</p>
<pre><code class="lang-auto">fRunningLoss = self.TrainModel()
  File ".\mainModel.py", line 
100, in TrainModel
    outputs = self.mModel(images)
  File "C:\Users\AppData\Local\Programs\Python\Python39\lib\site-packages\torch\nn\modules\module.py", line 1501, in _call_impl
    return forward_call(*args, **kwargs)
  File ".\models\feedforward.py", line 20, in forward
    x = F.relu(self.conv1(x))
  File "C:\Users\AppData\Local\Programs\Python\Python39\lib\site-packages\torch\nn\modules\module.py", line 1501, in _call_impl
    return forward_call(*args, **kwargs)
  File "C:\Users\3058388\AppData\Local\Programs\Python\Python39\lib\site-packages\torch\nn\modules\conv.py", line 463, in forward
    return self._conv_forward(input, self.weight, self.bias)
  File "C:\Users\AppData\Local\Programs\Python\Python39\lib\site-packages\torch\nn\modules\conv.py", line 459, in _conv_forward
    return F.conv2d(input, weight, bias, self.stride,
RuntimeError: Input type (unsigned char) and bias type (float) should be the same

</code></pre>

ptrblck: <p>Add the missing <code>ToTensor()</code> transformation to your custom datasets.</p>