CrossEntropyLoss в PyTorch уже реализован с Softmax:
https://pytorch.org/docs/stable/nn.html#torch.nn.CrossEntropyLoss
Этот критерий объединяет nn.LogSoftmax () и nn.NLLLoss () в одном классе.
EDIT :
Ответ на вашу вторую часть ответа немного сложнее. Там может быть несколько причин для снижения точности. Теоретически, поскольку добавленный вами слой softmax может предсказать правильный ответ с разумной точностью, следующий слой должен быть в состоянии сделать то же самое, сохранив максимальное значение с идентичностью между двумя последними слоями. Хотя softmax снова нормализует эти ограниченные выходы (между 0 и 1), он может изменить способ их распределения, но все же может сохранить максимум и, следовательно, прогнозируемый класс.
Однако на практике все немного по-другому. Когда у вас есть двойной softmax в выходном слое, вы в основном меняете выходную функцию таким образом, что она изменяет градиенты, которые распространяются в вашей сети. Softmax с перекрестной энтропией является предпочтительной функцией потерь из-за градиентов, которые он производит. Вы можете доказать это себе, вычислив градиенты функции стоимости, и учесть тот факт, что каждая «активация» (softmax) ограничена между 0 и 1. Дополнительный softmax «позади» оригинала просто умножает градиенты на значения между 0 и 1 и, таким образом, уменьшая значение. Это влияет на обновления весов. Может быть, это можно исправить, изменив скорость обучения, но это настоятельно не рекомендуется. Просто сделайте один софтмакс, и все готово.
См. книгу Майкла Нильсена, глава 3 для более подробного объяснения этого.