Probably due to my unclear understanding of the forward pass function, I have made a mistake in the following code:
# data loader parameters
training_loader = torch.utils.data.DataLoader(training_data,
                                           batch_size=12, 
                                           num_workers=0,
                                           shuffle=True)


class Net(nn.Module):
    ### TODO: choose an architecture, and complete the class
    def __init__(self):
        super(Net, self).__init__()
        ## Define layers of a CNN

        total_dog_classes = 133

        self.conv1 = nn.Conv2d(3, 32, 3, padding = 1)    
        self.norm2d1 = nn.BatchNorm2d(32)
        self.conv2 = nn.Conv2d(32, 64, 3, padding = 1) 
        self.conv3 = nn.Conv2d(64, 128, 3, padding = 1)  
        self.conv4 = nn.Conv2d(128, 256, 3, padding = 1)

        ## Max Pooling Layer
        self.pool = nn.MaxPool2d(2, 2)

        ## Droput Layer
        self.dropout = nn.Dropout(0.2)

        ## Linear Layer
        self.fc1 = nn.Linear(256 * 7 * 7, 512)
        self.fc2 = nn.Linear(512, total_dog_classes)


    def forward(self, x):
        ## Define forward behavior
        x = self.pool(F.relu(self.norm2d1(self.conv1(x))))
        print(x.shape)

        x = self.pool(F.relu(self.conv2(x)))
        print(x.shape)

        x = self.pool(F.relu(self.conv3(x)))
        print(x.shape)

        x = self.pool(F.relu(self.conv4(x)))
        print(x.shape)

        # Flatten Image and Add Dropout Layer
        x = self.dropout(x.view(-1, 256 * 7 * 7))

        # Add Second Hidden Layer
        x = self.dropout(F.relu(self.fc1(x)))
        x = self.fc2(x)
        return x

and here is the printed output of shapes:
torch.Size([12, 32, 112, 112])
torch.Size([12, 64, 56, 56])
torch.Size([12, 128, 28, 28])
torch.Size([12, 256, 14, 14])
torch.Size([48, 133])

Leading to  ValueError: Expected input batch_size (48) to match target batch_size (12).  I would really be helped if the calculations are also explained. Thanks!