Trying to create a Binary Classifier but there is a ValueError

I am trying to create a Binary Classifier for dogs and cats. Here is the model of the network:
ConvNet(
(conv1): Conv2d(3, 32, kernel_size=(7, 7), stride=(1, 1))
(max_pool): MaxPool2d(kernel_size=3, stride=3, padding=0, dilation=1, ceil_mode=False)
(conv2): Conv2d(32, 64, kernel_size=(3, 3), stride=(1, 1))
(avg_pool): AvgPool2d(kernel_size=2, stride=2, padding=0)
(fc1): Linear(in_features=131072, out_features=100, bias=True)
(fc2): Linear(in_features=100, out_features=1, bias=True)
)
This is the code I use to train the network:

loss = nn.BCELoss()
optimizer = optim.RMSprop(net.parameters(), lr=0.001)
for epoch in range(2):
    running_loss = 0.0
    correct = 0
    net.train()
    for data, target in training_set:
        target = target.float()
        optimizer.zero_grad()
        output = net(data)
        loss = loss(output, target)
        loss.backward()
        optimizer.step()
        running_loss += loss.item()

I am getting this error when calling the line > loss = loss(output, target)

... in binary_cross_entropy
    raise ValueError("Target and input must have the same number of elements. target nelement ({}) "
ValueError: Target and input must have the same number of elements. target nelement (32) != input nelement (1)

From what I understand the output of my network is 1 but the labels of the dataset are 32 because of the batch size.

What are the shapes of target, data and output?

target: torch.Size([32]), data: torch.Size([32, 3, 64, 64]), and output: torch.Size([1, 1])

I think there’s something wrong happening in your model because your 32 examples that should be ran in parallel disappears into a single example as the output. The output should be torch.size([32, 1]). Could you show how net looks like?

That’s also what I suspect but I don’t know how to fix it. Here is the model if you want to see:

class ConvNet(nn.Module):

    def __init__(self):
        super(ConvNet, self).__init__()
        self.conv1 = nn.Conv2d(3, 32, 7)
        self.max_pool = nn.MaxPool2d(3)
        self.conv2 = nn.Conv2d(32, 64, 3)
        self.avg_pool = nn.AvgPool2d(2)
        self.fc1 = nn.Linear(64 * 64 * 32, 100)  # height * width * batch_size
        self.fc2 = nn.Linear(100, 1)

    def forward(self, x):
        x = self.max_pool(f.relu(self.conv1(x)))
        x = self.avg_pool(f.relu(self.conv2(x)))
        x = x.view(-1, 64 * 64 * 32)
        x = f.relu(self.fc1(x))
        x = f.relu(self.fc2(x))
        x = f.sigmoid(x)
        return x

After the two conv layers the shape is [32, 64, 8, 8] so when you’re doing .view the shapes get screwed up. I modified your net to

class ConvNet(nn.Module):

    def __init__(self):
        super(ConvNet, self).__init__()
        self.conv1 = nn.Conv2d(3, 32, 7)
        self.max_pool = nn.MaxPool2d(3)
        self.conv2 = nn.Conv2d(32, 64, 3)
        self.avg_pool = nn.AvgPool2d(2)
        self.fc1 = nn.Linear(64*8*8, 100)  # height * width * batch_size
        self.fc2 = nn.Linear(100, 1)

    def forward(self, x):
        x = self.max_pool(f.relu(self.conv1(x)))
        x = self.avg_pool(f.relu(self.conv2(x)))
        x = x.view(-1, 64 * 8 * 8)
        x = f.relu(self.fc1(x))
        x = f.relu(self.fc2(x))
        x = f.sigmoid(x)
        return x
1 Like

Wow! Thanks! It works now. :blush:

May I ask how did you get the shape of the conv layers?