2017-03-04 60 views
2

有一種數值穩定的方法來計算softmax函數嗎? 我得到的值是在神經網絡代碼中變成了Nans。商業穩定的softmax

np.exp(x)/np.sum(np.exp(y)) 
+2

這裏的答案顯示了更好的方法來計算softmax:http://stackoverflow.com/questions/34968722/softmax-function-python –

+2

@ajcr在這個鏈接接受的答案實際上是不好的建議。阿布舍克,即使他們第一次似乎不明白爲什麼這是正確的事情,OP所做的事情。除了溢出之外,softmax中沒有數字上的困難步驟。因此,在數學上相同的情況下,將所有輸入移到左邊,消除了溢出的可能性,因此在數值上是一種改進。 –

+0

是的,儘管接受答案的作者在評論中承認,減去最大值並沒有引入「必要的術語」,但實際上提高了數值穩定性(也許應該編輯答案......)。在任何情況下,數值穩定性的問題都可以在其他答案中找到。 @AbhishekBhatia:你認爲這個鏈接令人滿意地回答你的問題,或者這裏的新答案是有益的嗎? –

回答

11

softmax exp(x)/ sum(exp(x))實際上在數值上表現良好。它只有正項,所以我們不必擔心失去顯着性,分母至少與分子一樣大,所以結果保證在0和1之間。

唯一的意外可能是在指數中發生過度或不足的情況。單個或下溢所有元素的溢出x將使輸出或多或少無用。

但是很容易以防止通過使用身份SOFTMAX(X)= SOFTMAX(X + c)中保存用於任何標量C:減去最大(X)從X葉一個只有非正項的向量,排除溢出並且至少有一個零元素排除了一個正在消失的分母(在一些但不是全部條目中下溢是無害的)。

1

計算softmax函數沒有什麼問題,因爲它是在你的情況。問題似乎來自爆炸梯度或您的訓練方法的這類問題。通過「限幅值」或「選擇權重的正確初始分佈」來關注那些事項。

+2

*「計算softmax函數沒有什麼問題,因爲它是你的情況。」*嘗試用它計算'softmax(800)'。 –

+0

如果你想在這個尺度上工作,那麼在Python中做任何事情都會導致「inf」中的任何東西都不穩定。 –

0

SOFTMAX功能很容易出現兩個問題:溢出下溢

溢出:當非常大的數字是近似作爲infinity

下溢發生:發生在非常小的數量時rs(數字線附近的零)近似爲(即,圓形到)作爲zero

爲了克服在SOFTMAX計算這些問題,一個共同的竅門是輸入向量通過從所有元素減去它的最大元件位移。對於輸入矢量x,定義z使得:

z = x-max(x) 

再取新的(穩定的)矢量z


實施例的SOFTMAX:

In [266]: def stable_softmax(x): 
    ...:  z = x - max(x) 
    ...:  numerator = np.exp(z) 
    ...:  denominator = np.sum(numerator) 
    ...:  softmax = numerator/denominator 
    ...:  return softmax 
    ...: 

In [267]: vec = np.array([1, 2, 3, 4, 5]) 

In [268]: stable_softmax(vec) 
Out[268]: array([ 0.01165623, 0.03168492, 0.08612854, 0.23412166, 0.63640865]) 

In [269]: vec = np.array([12345, 67890, 99999999]) 

In [270]: stable_softmax(vec) 
Out[270]: array([ 0., 0., 1.]) 

有關更多詳細信息,請參見章節Numerical Computation in deep learning book。