ReLU上的花樣
CNN出現以來,感覺在各個地方,即便是非常小的地方都有點可以挖掘。比如ReLU。
ReLU的有效性體現在兩個方面:
- 克服梯度消失的問題
- 加快訓練速度
而這兩個方面是相輔相成的,因為克服了梯度消失問題,所以訓練才會快。
ReLU的起源,在這片博文里,對ReLU的起源的介紹已經很詳細了,包括如何從生物神經衍生出來,如何與稀疏性進行關聯等等。
其中有一段特別精彩的話我引用在下面:
幾十年的機器學習發展中,我們形成了這樣一個概念:非線性激活函數要比線性激活函數更加先進。
尤其是在布滿Sigmoid函數的BP神經網絡,布滿徑向基函數的SVM神經網絡中,往往有這樣的幻覺,非線性函數對非線性網絡貢獻巨大。
該幻覺在SVM中更加嚴重。核函數的形式並非完全是SVM能夠處理非線性數據的主力功臣(支持向量充當着隱層角色)。
那么在深度網絡中,對非線性的依賴程度就可以縮一縮。另外,在上一部分提到,稀疏特征並不需要網絡具有很強的處理線性不可分機制。
綜合以上兩點,在深度學習模型中,使用簡單、速度快的線性激活函數可能更為合適。
而本文要講的,則是ReLU上的改進,所謂麻雀雖小,五臟俱全,ReLU雖小,但也是可以改進的。
ReLU的種類
ReLU的區分主要在負數端,根據負數端斜率的不同來進行區分,大致如下圖所示。
普通的ReLU負數端斜率是0,Leaky ReLU則是負數端有一個比較小的斜率,而PReLU則是在后向傳播中學習到斜率。而Randomized Leaky ReLU則是使用一個均勻分布在訓練的時候隨機生成斜率,在測試的時候使用均值斜率來計算。
效果
其中,NDSB數據集是Kaggle的比賽,而RReLU正是在這次比賽中嶄露頭角的。
通過上述結果,可以看到四點:
- 對於leaky ReLU來說,如果斜率很小,那么與ReLU並沒有大的不同,當斜率大一些時,效果就好很多。
- 在訓練集上,PReLU往往能達到最小的錯誤率,說明PReLU容易過擬合。
- 在NSDB數據集上RReLU的提升比cifar10和cifar100上的提升更加明顯,而NSDB數據集比較小,從而可以說明,RReLU在與過擬合的對抗中更加有效
- 對於RReLU來說,還需要研究一下隨機化得斜率是怎樣影響訓練和測試過程的。
參考文獻
[1]. Xu B, Wang N, Chen T, et al. Empirical evaluation of rectified activations in convolutional network[J]. arXiv preprint arXiv:1505.00853, 2015.
ReLU、LReLU、PReLU、CReLU、ELU、SELU
ReLU
tensorflow中:tf.nn.relu(features, name=None)
LReLU
(Leaky-ReLU)
其中aiai是固定的。ii表示不同的通道對應不同的aiai.
tensorflow中:tf.nn.leaky_relu(features, alpha=0.2, name=None)
PReLU
其中aiai是可以學習的的。如果ai=0ai=0,那么 PReLU 退化為ReLU;如果 aiai是一個很小的固定值(如ai=0.01ai=0.01),則 PReLU 退化為 Leaky ReLU(LReLU)。
PReLU 只增加了極少量的參數,也就意味着網絡的計算量以及過擬合的危險性都只增加了一點點。特別的,當不同 channels 使用相同的aiai時,參數就更少了。BP 更新aiai時,采用的是帶動量的更新方式(momentum)。
tensorflow中:沒找到啊!
CReLU
(Concatenated Rectified Linear Units)
tensorflow中:tf.nn.crelu(features, name=None)
ELU
其中α是一個可調整的參數,它控制着ELU負值部分在何時飽和。
右側線性部分使得ELU能夠緩解梯度消失,而左側軟飽能夠讓ELU對輸入變化或噪聲更魯棒。ELU的輸出均值接近於零,所以收斂速度更快
tensorflow中:tf.nn.elu(features, name=None)
SELU
經過該激活函數后使得樣本分布自動歸一化到0均值和單位方差(自歸一化,保證訓練過程中梯度不會爆炸或消失,效果比Batch Normalization 要好)
其實就是ELU乘了個lambda,關鍵在於這個lambda是大於1的。以前relu,prelu,elu這些激活函數,都是在負半軸坡度平緩,這樣在activation的方差過大的時候可以讓它減小,防止了梯度爆炸,但是正半軸坡度簡單的設成了1。而selu的正半軸大於1,在方差過小的的時候可以讓它增大,同時防止了梯度消失。這樣激活函數就有一個不動點,網絡深了以后每一層的輸出都是均值為0方差為1。
tensorflow中:tf.nn.selu(features, name=None)