В прямое время мы (с й = входным вектором, Y = выходной вектором, F = logsoftmax, I = I-й компонент):
yi = f(xi)
= log(exp(xi)/sum_j(exp(xj)))
= xi - log(sum_j(exp(xj)))
При вычислении якобиана Jf Р у вас есть (я-я строка):
dyi/dxi = 1 - exp(xi)/sum_j(exp(xj))
И к различным, чем я:
dyi/dxk = - exp(xk)/sum_j(exp(xj))
Это дает для Jf:
1-E(x1) -E(x2) -E(x3) ...
-E(x1) 1-E(x2) -E(x3) ...
-E(x1) -E(x2) 1-E(x3) ...
...
С E(xi) = exp(xi)/sum_j(exp(xj))
Если мы называем gradInput Градиент входные данные WRT и gradOutput выход градиента орбиты относительно обратного распространения дает (правило цепи):
gradInputi = sum_j(gradOutputj . dyj/dxi)
Это эквивалентно:
gradInput = transpose(Jf) . gradOutput
Который, наконец, дает для г-го компонента:
gradInputi = gradOutputi - E(xi) . sum_j(gradOutputj)
Таким образом, первый цикл предварительно вычисляет sum_j(gradOutputj)
и последний выше термин, т.е. я-я компонента град. вход - за исключением отсутствия 1/sum_j(exp(xj))
для экспоненциального члена в реализации факела (вышеупомянутое исчисление должно быть проверено дважды, даже если оно звучит правильно и объясняет текущую реализацию).
UPDATE: нет никаких проблем с отсутствующего1/sum_j(exp(xj))
срок. Так как якобиан вычисляется на значение по вывода, так как это ранее вычисленный выход именно распределение лог-SoftMax речь идет о том, что сумма Экспоненциальная этого распределения не 1:
sum_j(exp(outputj)) = sum_j(exp(log(exp(inputj)/sum_k(exp(inputk)))
= sum_j( exp(inputj)/sum_k(exp(inputk) )
= 1
Так нет необходимо указать этот термин в реализации, который дает (для x = выход):
gradInputi = gradOutputi - exp(outputi) . sum_j(gradOutputj)