神經網路之啟用函式(Activation Function)(附maxout)
啟用函式參考的原文地址http://blog.csdn.net/cyh_24/article/details/50593400
maxout部分參考的原文地址http://www.cnblogs.com/tornadomeet/p/3428843.html
Why use activation functions?
啟用函式通常有如下一些性質:
- 非線性: 當啟用函式是線性的時候,一個兩層的神經網路就可以逼近基本上所有的函數了。但是,如果啟用函式是恆等啟用函式的時候(即f(x)=x),就不滿足這個性質了,而且如果MLP使用的是恆等啟用函式,那麼其實整個網路跟單層神經網路是等價的。
- 可微性: 當優化方法是基於梯度的時候,這個性質是必須的。
- 單調性: 當啟用函式是單調的時候,單層網路能夠保證是凸函式。
- f(x)≈x: 當啟用函式滿足這個性質的時候,如果引數的初始化是random的很小的值,那麼神經網路的訓練將會很高效;如果不滿足這個性質,那麼就需要很用心的去設定初始值。
- 輸出值的範圍: 當啟用函式輸出值是 有限 的時候,基於梯度的優化方法會更加 穩定,因為特徵的表示受有限權值的影響更顯著;當啟用函式的輸出是 無限 的時候,模型的訓練會更加高效,不過在這種情況小,一般需要更小的learning rate.
這些性質,也正是我們使用啟用函式的原因!
Activation Functions.
Sigmoid
Sigmoid 是常用的非線性的啟用函式,它的數學形式如下:
正如前一節提到的,它能夠把輸入的連續實值“壓縮”到0和1之間。
特別的,如果是非常大的負數,那麼輸出就是0;如果是非常大的正數,輸出就是1.
sigmoid 函式曾經被使用的很多,不過近年來,用它的人越來越少了。主要是因為它的一些 缺點:
- Sigmoids saturate and kill gradients. (saturate 這個詞怎麼翻譯?飽和?)sigmoid 有一個非常致命的缺點,當輸入非常大或者非常小的時候(saturation),這些神經元的梯度是接近於0的,從圖中可以看出梯度的趨勢。所以,你需要尤其注意引數的初始值來儘量避免saturation的情況。如果你的初始值很大的話,大部分神經元可能都會處在saturation的狀態而把gradient kill掉,這會導致網路變的很難學習。
- Sigmoid 的 output 不是0均值. 這是不可取的,因為這會導致後一層的神經元將得到上一層輸出的非0均值的訊號作為輸入。
產生的一個結果就是:如果資料進入神經元的時候是正的(e.g. x>0 elementwise in f=wTx+b),那麼 w 計算出的梯度也會始終都是正的。
當然了,如果你是按batch去訓練,那麼那個batch可能得到不同的訊號,所以這個問題還是可以緩解一下的。因此,非0均值這個問題雖然會產生一些不好的影響,不過跟上面提到的 kill gradients 問題相比還是要好很多的。
tanh
tanh 是上圖中的右圖,可以看出,tanh 跟sigmoid還是很像的,實際上,tanh 是sigmoid的變形:
與 sigmoid 不同的是,tanh 是0均值的。因此,實際應用中,tanh 會比 sigmoid 更好(畢竟去粗取精了嘛)。
ReLU
近年來,ReLU 變的越來越受歡迎。它的數學表示式如下:
很顯然,從圖左可以看出,輸入訊號<0時,輸出都是0,>0 的情況下,輸出等於輸入。w 是二維的情況下,使用ReLU之後的效果如下:
ReLU 的優點:
- Krizhevsky et al. 發現使用 ReLU 得到的SGD的收斂速度會比 sigmoid/tanh 快很多(看右圖)。有人說這是因為它是linear,而且 non-saturating
- 相比於 sigmoid/tanh,ReLU 只需要一個閾值就可以得到啟用值,而不用去算一大堆複雜的運算。
ReLU 的缺點: 當然 ReLU 也有缺點,就是訓練的時候很”脆弱”,很容易就”die”了. 什麼意思呢?
舉個例子:一個非常大的梯度流過一個 ReLU 神經元,更新過引數之後,這個神經元再也不會對任何資料有啟用現象了。
如果這個情況發生了,那麼這個神經元的梯度就永遠都會是0.
實際操作中,如果你的learning rate 很大,那麼很有可能你網路中的40%的神經元都”dead”了。
當然,如果你設定了一個合適的較小的learning rate,這個問題發生的情況其實也不會太頻繁。
Leaky-ReLU、P-ReLU、R-ReLU
Leaky ReLUs: 就是用來解決這個 “dying ReLU” 的問題的。與 ReLU 不同的是:
這裡的 α 是一個很小的常數。這樣,即修正了資料分佈,又保留了一些負軸的值,使得負軸資訊不會全部丟失。
關於Leaky ReLU 的效果,眾說紛紜,沒有清晰的定論。有些人做了實驗發現 Leaky ReLU 表現的很好;有些實驗則證明並不是這樣。
Parametric ReLU: 對於 Leaky ReLU 中的α,通常都是通過先驗知識人工賦值的。
然而可以觀察到,損失函式對α的導數我們是可以求得的,可不可以將它作為一個引數進行訓練呢?
Kaiming He的論文《Delving Deep into Rectifiers: Surpassing Human-Level Performance on ImageNet Classification》指出,不僅可以訓練,而且效果更好。
公式非常簡單,反向傳播至未啟用前的神經元的公式就不寫了,很容易就能得到。對α的導數如下:
δyiδα=0,(ifyi>0),else=yi原文說使用了Parametric ReLU後,最終效果比不用提高了1.03%.
Randomized ReLU:
Randomized Leaky ReLU 是 leaky ReLU 的random 版本 (α 是random的).
它首次試在 kaggle 的NDSB 比賽中被提出的。
核心思想就是,在訓練過程中,α 是從一個高斯分佈 U(l,u) 中 隨機出來的,然後再測試過程中進行修正(有點像dropout的用法)。
數學表示如下:
在測試階段,把訓練過程中所有的 αij 取個平均值。NDSB
冠軍的 α 是從 U(3,8) 中隨機出來的。那麼,在測試階段,啟用函式就是就是:
看看 cifar-100 中的實驗結果:
Maxout
maxout出現在ICML2013上,作者Goodfellow將maxout和dropout結合後,號稱在MNIST, CIFAR-10, CIFAR-100, SVHN這4個數據上都取得了start-of-art的識別率。
從論文中可以看出,maxout其實一種激發函式形式。通常情況下,如果激發函式採用sigmoid函式的話,在前向傳播過程中,隱含層節點的輸出表達式為:
其中W一般是2維的,這裡表示取出的是第i列,下標i前的省略號表示對應第i列中的所有行。但如果是maxout激發函式,則其隱含層節點的輸出表達式為:
這裡的W是3維的,尺寸為d*m*k,其中d表示輸入層節點的個數,m表示隱含層節點的個數,k表示每個隱含層節點對應了k個”隱隱含層”節點,這k個”隱隱含層”節點都是線性輸出的,而maxout的每個節點就是取這k個”隱隱含層”節點輸出值中最大的那個值。因為激發函式中有了max操作,所以整個maxout網路也是一種非線性的變換。因此當我們看到常規結構的神經網路時,如果它使用了maxout激發,則我們頭腦中應該自動將這個”隱隱含層”節點加入。參考一個日文的maxout ppt 中的一頁ppt如下:
ppt中箭頭前後示意圖大家應該可以明白什麼是maxout激發函數了。
maxout的擬合能力是非常強的,它可以擬合任意的的凸函式。最直觀的解釋就是任意的凸函式都可以由分段線性函式以任意精度擬合(學過高等數學應該能明白),而maxout又是取k個隱隱含層節點的最大值,這些”隱隱含層"節點也是線性的,所以在不同的取值範圍下,最大值也可以看做是分段線性的(分段的個數與k值有關)。論文中的圖1如下(它表達的意思就是可以擬合任意凸函式,當然也包括了ReLU了):
作者從數學的角度上也證明了這個結論,即只需2個maxout節點就可以擬合任意的凸函數了(相減),前提是”隱隱含層”節點的個數可以任意多,如下圖所示:
所以,Maxout 具有 ReLU 的優點(如:計算簡單,不會 saturation),同時又沒有 ReLU 的一些缺點 (如:容易 go die)。不過呢,還是有一些缺點的嘛:就是把引數double了。
還有其他一些啟用函式,請看下錶:
How to choose a activation function?
怎麼選擇啟用函式呢?
我覺得這種問題不可能有定論的吧,只能說是個人建議。
如果你使用 ReLU,那麼一定要小心設定 learning rate,而且要注意不要讓你的網路出現很多 “dead” 神經元,如果這個問題不好解決,那麼可以試試 Leaky ReLU、PReLU 或者 Maxout.
友情提醒:最好不要用 sigmoid,你可以試試 tanh,不過可以預期它的效果會比不上 ReLU 和 Maxout.
還有,通常來說,很少會把各種啟用函式串起來在一個網路中使用的。
Reference
Please feel free to contract me if you have any questions.