Search code examples
machine-learningdeep-learningpytorchneural-networkconv-neural-network

How to resolve runtime error in CNN model related to mismatch input size?


I am trying to run a CNN model on a synthetic dataset consisting of 4000 sample of semi simple random points with 2 features and 1 cluster per class and input data size x is [4000,2] and corresponding labels size is [4000].

I understand that as original input tensor has shape [4000,2] where 4000=total number of samples and 2=number of features and my input to Conv1d layer should be 3d tensor [batch_size,1,2] where 1 is number of input channels and 2 is sequence length but when it runs through dataloader and train function it becomes [1,batch_size,2] and that’s where issue arising. CNN is defined with its parameters as:

class Net(nn.Module):
    def __init__(self, Bias):
        super(Net, self).__init__()
        self.conv1 = nn.Conv1d(1, 1, kernel_size=1, stride=1) 
        self.relu = nn.ReLU()                                 
        self.fc1 = nn.Linear(2, 20, bias = False)            
        self.fc2 = nn.Linear(20, 2, bias = False)
    def forward(self, x):
        x = self.relu(self.conv1(x))
        x = x.reshape(x.size(0), -1)
        x = self.relu(self.fc1(x))
        x = self.fc2(x)
        return x

epochs = 50
alpha = 1e-2
batch_size = 50
criterion = nn.CrossEntropyLoss()
model = Net(biases).to(device)
model = train(model.to(device),criterion,x,y,alpha,epochs,batch_size)

And I used following train function:

def train(model,criterion, x, y, alpha, epochs, batchsize):
    costs = []
    optimizer = torch.optim.SGD(model.parameters(), lr=alpha)    
    trainx, trainy, testx, testy= dataloader(x,y)
    x=trainx.float()
    y=trainy.float()
    data_train = torch.cat((x, y), dim=1)
    data_train_loader = DataLoader(data_train, batch_size=batchsize, shuffle=True)
    model.train()
    j = 0
    for i in range(epochs):
        for index,samples in enumerate(data_train_loader):
            j += 1
            x1 = samples[:,0:2]
            y1 = samples[:,2].long().reshape(-1,1)
            if (j%50 == 0):
                model.eval()
                acc = accuracy(model,testx,testy)
                print(f'Test accuracy is #{acc:.2f} , Iteration number is = {j}')
                model.train()
            cost = criterion(model(x1), y1.squeeze())
            optimizer.zero_grad()
            cost.backward()
            optimizer.step()        
            costs.append(float(cost))
    return model

And following is the error I get:

RuntimeError                              Traceback (most recent call last)
Cell In[17], line 7
      5 criterion = nn.CrossEntropyLoss()
      6 model = Net(biases).to(device)
----> 7 model=train(model.to(device),criterion,x,y,alpha,epochs,batch_size)
Cell In[15], line 40, in train(model, criterion, x, y, alpha, epochs, batchsize)
     38     print(f'Test accuracy is #{acc:.2f} , Iteration number is = {j}')
     39     model.train()
---> 40 cost = criterion(model(x1), y1.squeeze())
Cell In[16], line 11, in Net.forward(self, x)
     10 def forward(self, x):
---> 11     x = self.relu(self.conv1(x))

RuntimeError: Given groups=1, weight of size [1, 1, 1], expected input[1, 50, 2] to have 1 channels, but got 50 channels instead

How to solve this input dimension problem or to change the dimension requirement of model input?


Solution

  • When you do

    x1 = samples[:,0:2] # (batch_size, features)
    

    replace with the following to add the channel dimension. This is similar to unsqueeze, if you have numpy loaded you can replace None with np.newaxis which is more informative but the same thing.

    x1 = samples[:, None,0:2]  # (batch_size, 1, features)