I would try to use a loss function built for classification, e.g. nn.CrossEntropyLoss.
To do that, just swap this criterion with nn.MSELoss, remove the softmax in your model, and make sure your target tensors contain the class index for each sample.
I’m not sure, how batch_y is defined at the moment, but if it’s one-hour encoded, just call target = torch.argmax(batch_y, 1) and use target to compute the loss.