试图理解为Torch中LogSoftMax的输入计算渐变的代码

时间:2016-02-09 23:44:11

标签: mathematical-optimization torch gradient-descent softmax

代码来自:https://github.com/torch/nn/blob/master/lib/THNN/generic/LogSoftMax.c

我没有看到此代码如何计算渐变w.r.t到模块LogSoftMax的输入。令我困惑的是两个for循环正在做什么。

for (t = 0; t < nframe; t++)
{
sum = 0;
gradInput_data = gradInput_data0 + dim*t;
output_data = output_data0 + dim*t;
gradOutput_data = gradOutput_data0 + dim*t;

for (d = 0; d < dim; d++)
  sum += gradOutput_data[d];

for (d = 0; d < dim; d++)
  gradInput_data[d] = gradOutput_data[d] - exp(output_data[d])*sum;
 }
}

1 个答案:

答案 0 :(得分:4)

在前进时间我们有(x =输入向量,y =输出向量,f = logsoftmax,i =第i个分量):

yi = f(xi)
   = log( exp(xi) / sum_j(exp(xj)) )
   = xi - log( sum_j(exp(xj)) )

当你计算j的jacobian 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))

如果我们将gradInput命名为渐变w.r.t输入和gradOutput渐变w.r.t输出反向传播给出(链规则):

gradInputi = sum_j( gradOutputj . dyj/dxi )

这相当于:

gradInput = transpose(Jf) . gradOutput

最终给出了第i个组件:

gradInputi = gradOutputi - E(xi) . sum_j( gradOutputj )

因此,第一个循环预先计算sum_j( gradOutputj ),最后一个循环预先计算上一个项,即毕业的第i个分量。输入 - 除了在Torch实现中指数项缺少1 / sum_j(exp(xj))上述微积分应该经过双重检查,即使它听起来是正确的并解释了当前的实现)。 p>

更新缺少 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 )