《Deep Learning》(Ian Goodfellow & Yoshua Bengio & Aaron Courville)第四章「數值計算」中,談到了上溢出(overflow)和下溢出(underflow)對數值計算的影響,並以softmax函數和log softmax函數爲例進行了講解。這裏我再詳細地把它總結一下。函數
實數在計算機內用二進制表示,因此不是一個精確值,當數值太小的時候,被四捨五入爲0,這就是下溢出。此時若是對這個數再作某些運算(例如除以它)就會出問題。反之,當數值過大的時候,狀況就變成了上溢出。atom
softmax函數以下:
spa
從公式上看含義不是特別清晰,因此借用知乎上的一幅圖來講明(感謝原做者):3d
這幅圖極其清晰地代表了softmax函數是什麼,一圖勝千言。blog
一般狀況下,計算softmax函數值不會出現什麼問題,例如,當softmax函數表達式裏的全部 xi 都是一個「通常大小」的數值 c 時——也就是上圖中, z1=z2=z3=c 時,那麼,計算出來的函數值y1=y2=y3=1/3 。
可是,當某些狀況發生時,計算函數值就出問題了:get
因此怎樣規避這些問題呢?咱們能夠用同一個方法一口氣解決倆:
令 M=max(xi),i=1,2,⋯,n ,即 M 爲全部 xi 中最大的值,那麼咱們只須要把計算 f(xi)的值,改成計算 f(xi−M) 的值,就能夠解決上溢出、下溢出的問題了,而且,計算結果理論上仍然和 f(xi)保持一致。
舉個實例:仍是之前面的圖爲例,原本咱們計算 f(z2) ,是用「常規」方法來算的:
io
如今咱們改爲:
class
其中, M=3 是 z1,z2,z3 中的最大值。可見計算結果並未改變。這是怎麼作到的呢?經過簡單的代數運算就能夠參透其中的「祕密」:
技巧
經過這樣的變換,對任何一個 xi,減去M以後,e 的指數的最大值爲0,因此不會發生上溢出;同時,分母中也至少會包含一個值爲1的項,因此分母也不會下溢出(四捨五入爲0)。因此這個技巧沒什麼高級的技術含量。二進制
看似已經結案了,但仍然有一個問題:若是softmax函數中的分子發生下溢出,也就是前面所說的 c 爲負數,且 |c| 很大,此時分母是一個極小的正數,有可能四捨五入爲0的狀況,此時,若是咱們把softmax函數的計算結果再拿去計算 log,即 log softmax,其實就至關於計算 log(0) ,因此會獲得 −∞ ,但這其實是錯誤的,由於它是由舍入偏差形成的計算錯誤。因此,有沒有一個方法,能夠把這個問題也解決掉呢?
答案仍是採用和前面相似的策略來計算 log softmax 函數值:
你們看到,在最後的表達式中,會產生下溢出的因素已經被消除掉了——求和項中,至少有一項的值爲1,這使得log後面的值不會下溢出,也就不會發生計算 log(0) 的悲劇。在不少數值計算的library中,都採用了此類方法來保持數值穩定。