Given groups=1, weight of size [32, 1, 3, 3], expected input[100, 3, 112, 112] to have 1 channels, but got 3 channels instead

username: Oualid
cooked: <p>I am trying to train a CNN classifier with PyTorch for traffic sign recognition GTSRB.</p>
<p>I downloaded <strong>GTSRB_Final_Training_Images.zip</strong> and <strong>GTSRB_Final_Test_Images.zip</strong> and putted them under GTSRB/Train and GTSRB/Test respectively.</p>
<p>My code:</p>
<pre><code class="lang-auto">
import torch
import torch.nn as nn
import torch.optim as optim

device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")

class Flatten(nn.Module):
    def forward(self, x):
        return x.view(x.shape[0], -1)    

model_cnn = nn.Sequential(nn.Conv2d(1, 32, 3, padding=1), nn.ReLU(),
                          nn.Conv2d(32, 32, 3, padding=1, stride=2), nn.ReLU(),
                          nn.Conv2d(32, 64, 3, padding=1), nn.ReLU(),
                          nn.Conv2d(64, 64, 3, padding=1, stride=2), nn.ReLU(),
                          nn.Flatten(),
                          nn.Linear(7*7*64, 100), nn.ReLU(),
                          nn.Linear(100, 10)).to(device)

data_transforms = transforms.Compose([
    transforms.Resize([112, 112]),
    transforms.ToTensor()
    ])

from torchvision import datasets, transforms
from torch.utils.data import DataLoader

train_data_path = "GTSRB/Train"
test_data_path = "GTSRB/Test"

train_data = datasets.ImageFolder(root = train_data_path, transform = data_transforms)
test_data = datasets.ImageFolder(root = test_data_path, transform = data_transforms)

train_loader = DataLoader(train_data, batch_size = 100, shuffle=True)
test_loader = DataLoader(test_data, batch_size = 100, shuffle=False)

def epoch(loader, model, opt=None):
    total_loss, total_err = 0.,0.
    for X,y in loader:
        X,y = X.to(device), y.to(device)
        yp = model(X)
        loss = nn.CrossEntropyLoss()(yp,y)
        if opt:
            opt.zero_grad()
            loss.backward()
            opt.step()
        
        total_err += (yp.max(dim=1)[1] != y).sum().item()
        total_loss += loss.item() * X.shape[0]
    return total_err / len(loader.dataset), total_loss / len(loader.dataset)

opt = optim.SGD(model_cnn.parameters(), lr=1e-1)
for _ in range(10):
    train_err, train_loss = epoch(train_loader, model_cnn, opt)
    test_err, test_loss = epoch(test_loader, model_cnn)
    print(*("{:.6f}".format(i) for i in (train_err, train_loss, test_err, test_loss)), sep="\t")
</code></pre>
<p>The error message:</p>
<pre><code class="lang-auto">~\anaconda3\envs\lab01\lib\site-packages\torch\nn\modules\conv.py in _conv_forward(self, input, weight, bias)
    394                             _pair(0), self.dilation, self.groups)
    395         return F.conv2d(input, weight, bias, self.stride,
--&gt; 396                         self.padding, self.dilation, self.groups)
    397 
    398     def forward(self, input: Tensor) -&gt; Tensor:

RuntimeError: Given groups=1, weight of size [32, 1, 3, 3], expected input[100, 3, 112, 112] to have 1 channels, but got 3 channels instead
</code></pre>
<p>What is wrong?</p>

username: ptrblck
cooked: <p>The first conv layer expects input tensors with a single channel, while your inputs contain 3 channels.<br>
You would thus either have to change the first layer to:</p>
<pre><code class="lang-python">nn.Conv2d(3, 32, 3, padding=1)
</code></pre>
<p>or use grayscale images.</p>

username: Oualid
cooked: <p>That makes sense!<br>
Thank you.</p>
<p>I also changed some other parameters in the model to get it work:</p>
<pre><code class="lang-auto">     nn.Linear(4096, 100), nn.ReLU(),
     nn.Linear(100, 44)).to(device)

</code></pre>