Can you try BCE loss instead? It calculates the probability of a class for each of the 20 classes. Or you could use MSE loss.
Your loss from this line:

loss = (softmax(x[i]) * softmax(recon_x[i]))

doesn’t seem correct. For each coordinate you have a value in the range [0, 1] from your softmax function. If your prediction (for a particular coordinate) is 0 and your target is 0, you have 0 loss. And if your prediction is 1 and your target is 1 you have loss of 1.
I suggest a simple MSE or BCE loss will do.