I have built a model and overfit the model for a small batch of 16 samples from the training set. When I calculate the accuracy for this same batch, I expect 100% accuracy. I have used two different methods to calculate accuracy and both of them give such different results.
My forward pass function:
def fwd_pass(X, y, train=False):
    if not train:
        with torch.no_grad():
            outputs = model(X)
            matches = (torch.argmax (outputs, dim = 1) == y).sum()
    
            acc = matches/len(y)
    
            loss = loss_fn(outputs, y)
        
        return acc, loss
        
    outputs = model(X)
    matches = (torch.argmax (outputs, dim = 1) == y).sum()

    acc = matches/len(y)

    loss = loss_fn(outputs, y)

    loss.backward()
    opt.step()
    model.zero_grad()
        
    return acc, loss

My train function:
def train(net, epochs, batch_size, X, y, val_X=None, val_y=None):
    accuracies = []
    losses = []
    val_accuracies = []
    val_losses = []
    
    for ep in tqdm(range(epochs)):
        for i in tqdm(range(0, len(X), batch_size)):
            batch_X = X[i:i+batch_size].to(device)
            batch_y = y[i:i+batch_size].to(device)
            
            acc, loss = fwd_pass(batch_X.float(), batch_y, train=True)
            
            torch.cuda.empty_cache()
            
        if val_X != None and val_y != None:
            val_acc, val_loss = fwd_pass(val_X.to(device), val_y.to(device))
        
        print(f'Ep: {ep+1} Acc: {round(float(acc), 5)} Loss: {round(float(loss), 5)}')
        
        if val_X != None and val_y != None:
            print(f'Val Acc: {round(float(val_acc), 5)} Val Loss: {round(float(val_loss), 5)}')
        
        accuracies.append(acc)
        losses.append(loss)
        
        if val_X != None and val_y != None:
            val_accuracies.append(val_acc)
            val_losses.append(val_loss)
            
    return accuracies, losses, val_accuracies, val_losses

Now here, I calculate the accuracies:
corr = 0
tot = 0


with torch.no_grad():
    for i in range(len(batch_1_X)):
        op = model(batch_1_X[i].view(1, 100, 8).transpose(1, 2).to(device).float())
        pred = torch.argmax(op)
        real = batch_1_y[i]
        
        if pred == real:
            corr += 1
        
        tot += 1
        
print(corr)
print(tot)

The above gives me the following output:
3
16

suggesting that only 3 out of 16 have been predicted correctly, even though the model has been overfit.
Now, this method:
corr = 0
tot = 0

with torch.no_grad():
    op = model(batch_1_X.transpose(1, 2).to(device).float())
    preds = torch.argmax(op, dim=1)
    for p, r in zip(preds, batch_1_y):
        if p == r:
            corr += 1
            
        tot += 1

print(corr)
print(tot)

gives me the output
16
16

suggesting that all predictions are correct
The most confusing part of all was this:
corr = 0
tot = 0
num = 16

with torch.no_grad():
    op = model(batch_1_X[0:num].transpose(1, 2).to(device).float())
    preds = torch.argmax(op, dim=1)
    for p, r in zip(preds, batch_1_y[0:num]):
        if p == r:
            corr += 1
            
        tot += 1

print(corr)
print(tot)

When num is equal to 16, the corr and tot values are 16 and 16. When num is equal to something like 1, 3, 4, 5, 6, 7, 8, 9,…, the corr and tot values are equal. But when num is 2, corr is 1 and tot is 2 suggesting that the model got only 1 of the 2 predictions right.
What is the mistake I am making that is giving me this unpredictable behaivior?