0

代碼來自輸入LogSoftMax代碼:https://github.com/torch/nn/blob/master/lib/THNN/generic/LogSoftMax.c試圖瞭解其計算漸變WRT在火炬

我沒有看到這個代碼是如何計算梯度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; 
} 
} 

回答

3

在前進時間,我們(其中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)) 

而且對於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梯度WRT輸入和gradOutput梯度WRT輸出反向傳播給人(鏈式法則):

gradInputi = sum_j(gradOutputj . dyj/dxi) 

這相當於:

gradInput = transpose(Jf) . gradOutput 

哪個最後給出了第i個分量:

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

所以第一環路預先計算sum_j(gradOutputj)和最後一個上述術語,畢業的即第i個分量。輸入 - 除了火炬實現中的指數項缺少1/sum_j(exp(xj))上述微積分應該可以重複檢查,儘管聽起來是正確的並且解釋當前實現)。

UPDATE:沒有與失蹤1/sum_j(exp(xj))長期沒有問題。由於雅可比計算上輸出值,因爲這以前計算的輸出恰恰是對數SOFTMAX分佈談到這個分佈的總和-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)