CrossEntropyLoss has a parameter called reduction which its default value is reduction='elementwise_mean'. That means it automatically devide the computed loss by all elements which is batch_size * VOCAB_SIZE.
If you do not want to device by the VOCAB_SIZE and only compute the mean of the loss with respect to each batch, then you should do the following:
## define the loss
loss_function = nn.CrossEntropyLoss(ignore_index=PAD, reduction='sum')

and in your training call it as follows
loss = loss_function(yhat, y) / len(y)