在前进的时候,我们有(x = 输入向量,y = 输出向量,f = logsoftmax,i = 第 i 个分量):
yi = f(xi)
= log( exp(xi) / sum_j(exp(xj)) )
= xi - log( sum_j(exp(xj)) )
在计算 f 的雅可比 Jf 时,您有(第 i 行):
dyi/dxi = 1 - exp(xi) / sum_j(exp(xj))
对于不同于 i 的 k:
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))
如果我们将梯度 wrt 输入命名为 gradInput 并将梯度 wrt 输出命名为反向传播给出(链式法则):
gradInputi = sum_j( gradOutputj . dyj/dxi )
这相当于:
gradInput = transpose(Jf) . gradOutput
最后给出了第 i 个组件:
gradInputi = gradOutputi - E(xi) . sum_j( gradOutputj )
因此,第一个循环预先计算sum_j( gradOutputj )
上述项,最后一个循环预先计算,即 grad 的第 i 个分量。输入 - 除了在 Torch 实现中缺少1 / sum_j(exp(xj))
指数项(上面的微积分可能应该仔细检查,即使它听起来正确并解释了当前的实现)。
更新:缺少 1 / sum_j(exp(xj))
术语没有问题。由于 jacobian 是根据输出值计算的,并且由于以前计算的输出恰好是 log-softmax 分布,因此该分布的 sum-exp 为 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 )