0
$\begingroup$

I am doing simple image classification using CNN. My accuracy always equals one divided by the number of classes. For example, for one class it is 100%, for two classes it is 50%, for three it is 33%, for four 25% and so on. Could you please help me with this issue? In what conditions something like this happens? The inputs to the network are 240*64 tensors. I have tried normalizing them but it didn't help. Here is the network I am using. This network is working well for MNIST data but not for my data:

       class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.conv1 = nn.Conv2d(1, 10, kernel_size=1)
        self.conv2 = nn.Conv2d(10, 20, kernel_size=5)
        self.conv2_drop = nn.Dropout2d()
        self.fc1 = nn.Linear(20*14*58, 50)
        self.fc2 = nn.Linear(50, 4)
        

    def forward(self, x):
        x = F.relu(F.max_pool2d(self.conv1(x), 2))
        x = F.relu(F.max_pool2d(self.conv2_drop(self.conv2(x)), 2))
        x = x.view(-1, 20*14*58)
        x = F.relu(self.fc1(x))
        x = F.dropout(x, training=self.training)
        x = self.fc2(x) 
        return F.log_softmax(x)

And here is the training procedure:

  network.train()
  pred=0
  correct=0
  for batch_idx, (data, target) in enumerate(train_loader):
    optimizer.zero_grad()
    output = network(data.double())
    loss = F.nll_loss(output, target)

    top_p, top_class = output.topk(1, dim=1)
    pred1 = top_class.flatten().long()  
    
    loss.backward()
    optimizer.step()
    pred = output.data.max(1, keepdim=True)[1]
    correct += pred.eq(target.data.view_as(pred)).sum()
      
    target = np.round(target.detach())           
    y_pred.extend(pred.tolist())
    y_true.extend(target.tolist())
    CF = confusion_matrix(y_true, y_pred)
    #print( skm.classification_report(y_true,y_pred))


    
    if batch_idx % log_interval == 0:
      print('Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}'.format(
        epoch, batch_idx * len(data), len(train_loader.dataset),
        100. * batch_idx / len(train_loader), loss.item()))
      train_losses.append(loss.item())
      train_counter.append(
        (batch_idx*64) + ((epoch-1)*len(train_loader.dataset)))
```
$\endgroup$
2
  • 1
    $\begingroup$ It looks like your classifier is not working better than chance. $\endgroup$ – mdewey Jun 10 at 15:21
  • $\begingroup$ Look at your confusion matrix. $\endgroup$ – Arya McCarthy Jun 10 at 18:52
2
$\begingroup$

If you find accuracy exactly equal to one of the class proportions, it may indicate that your classifier is just outputting a constant result - it labels every sample as one of the classes, and only gets the ones that are actually that class correct. This is especially true if the accuracy is equal to the majority class proportion, as it's the simplest way to "maximize" accuracy. If you find an accuracy close to one of the class proportions, your method may just be producing random results, but if you find accuracy exactly equal to a class proportion, it's a big red flag that you're just classifying everything as belonging to that class.

Take a look at your confusion matrix - is your classifier actually making different predictions, or is it outputting the same result regardless of input?

$\endgroup$
2
  • $\begingroup$ Thanks for your answer. I've checked the confusion matrix as well as the classification report. The precision, recall, and F1 score values are updating at every iteration. However, from the four labels that I have, it seems like the true predictions for labels '1' and '3' are significantly bigger than labels '2' and '4'. Do you have any opinion on what the reason might be? It seems like the network is predicting labels '2' and '4' only a few times. $\endgroup$ – gazelle Jun 11 at 10:40
  • $\begingroup$ Just an update, the problem solved with another training part and the suggested network by @Avelina in the next answer. $\endgroup$ – gazelle Jun 13 at 18:32
1
$\begingroup$

Whenever you see an accuracy of $\frac{1}{NumClasses}$ after a few epochs it is an immediate red flag that your network isn't learning anything at all. It may be outputting a constant - as Nuclear Hoagie suggested - or it could be outputting noise.

This can be due to vanishing gradients on the backwards pass, exploding gradients on the forwards pass, too much regularization, lack of normalization, or a number of other factors.

Without knowing the exact structure of your network it's difficult to point out what in particular is happening. If you update your question with a network structure we can further diagnose what the issue might be.

$\endgroup$
7
  • $\begingroup$ Thanks, Avelina. I have updated my post with the code. I have tried normalization but it didn't help. Could the problem come from the data itself? I am using tensors as input. Could the reason be the similarity between the tensors under different labels? I have also checked the confusion matrix. It seems like the network is more likely to predict two of the labels out of four most of the time. $\endgroup$ – gazelle Jun 11 at 10:57
  • $\begingroup$ @gazelle what framework are you using? I'm not familiar with the syntax used there. It doesn't look like tensorflow keras to me, nor does it look like pytorch code although I'm not very familiar with pytorch. Maybe your network architecture isn't particularly suited for the task. I tend to use exclusively 3x3 and 1x1 convolutions, with filter counts doubling after every couple convolutions, starting with 64 filters, but for mnist a lower number like 16 sounds good. $\endgroup$ – Avelina Jun 11 at 12:29
  • $\begingroup$ @gazelle can you try a network architecture i specify here? its a network i'm sure will work, so if it still doesn't work we know something else in your training code is broken. conv2d( 3x3, 16 filters ) -> relu -> batch norm -> max pool 2d conv2d( 3x3, 32 filters ) -> relu -> batch norm -> max pool 2d conv2d( 3x3, 64 filters ) -> relu -> batch norm -> flatten fully connected( 128 units ) -> relu -> batch norm fully connected( <num out classes> units ) -> softmax Also, can I ask the number of classes and the size of your input images? $\endgroup$ – Avelina Jun 11 at 12:35
  • $\begingroup$ thanks for the comment @Avelina. I have applied this network but I'm still getting 25% accuracy. My inputs are tensors of size 240*64 (with one channel) and I have 4 labels. The tensors are matrices from MATLAB. I have also tried converting them to images and feed them to the network but still I am getting 25% accuracy. $\endgroup$ – gazelle Jun 11 at 19:05
  • $\begingroup$ Dear @Avelina, the problem solved! Regarding your suggestion that if the accuracy is not changing then the problem is coming from the training part, I've found one of my old codes that the training part was working fine but the accuracies were so small. I've just replaced my network with your suggested network and it worked very well! Could I ask what is the reason behind this layer arrangement working so well? Or if there is a reference explaining this, I will be so happy to go through that. Thanks for all the help. $\endgroup$ – gazelle Jun 13 at 18:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.