Основываясь на комментариях, проблема в том, что hidden_copy
никогда не посещается во время обратного прохода.
Когда вы выполняете обратный цикл, следует за графом вычислений в обратном направлении, начиная с loss_T
, и работает в обратном направлении ко всем листам. узлы. Он посещает только тензоры, которые были использованы для вычисления loss_T
. Если тензор не является частью этого обратного пути, он не будет посещен и его grad
член не будет обновлен. В основном, если создать копию тензора и затем не использовать ее для вычисления loss_T
, это приводит к «тупику» в графе вычислений.
Для иллюстрации взгляните на эту диаграмму, представляющую упрощенное представление вычислительного графа. Каждый узел графа является тензором, ребра которого указывают на прямых потомков.
Обратите внимание: если мы пойдем по пути от loss_T
к листьям, мы никогда не посетим hidden_conv
. Обратите внимание, что лист - это тензор без потомков, и в этом случае input
является единственным листом.
Это чрезвычайно упрощенный граф вычислений, используемый для демонстрации точки. Конечно, в действительности, вероятно, существует гораздо больше узлов между input
и hidden
и между hidden
и output_T
, а также другими листовыми тензорами, поскольку веса слоев почти наверняка равны листам.