原來ReLU這么好用!一文帶你深度了解ReLU激活函數(shù)!
在神經(jīng)網(wǎng)絡中,激活函數(shù)負責將來自節(jié)點的加權輸入轉(zhuǎn)換為該輸入的節(jié)點或輸出的激活。ReLU 是一個分段線性函數(shù),如果輸入為正,它將直接輸出,否則,它將輸出為零。它已經(jīng)成為許多類型神經(jīng)網(wǎng)絡的默認激活函數(shù),因為使用它的模型更容易訓練,并且通常能夠獲得更好的性能。在本文中,我們來詳細介紹一下ReLU,主要分成以下幾個部分:
1、Sigmoid 和 Tanh 激活函數(shù)的局限性
2、ReLU(Rectified Linear Activation Function)
3、如何實現(xiàn)ReLU
4、ReLU的優(yōu)點
5、使用ReLU的技巧
1. Sigmoid 和 Tanh 激活函數(shù)的局限性
一個神經(jīng)網(wǎng)絡由層節(jié)點組成,并學習將輸入的樣本映射到輸出。對于給定的節(jié)點,將輸入乘以節(jié)點中的權重,并將其相加。此值稱為節(jié)點的summed activation。然后,經(jīng)過求和的激活通過一個激活函數(shù)轉(zhuǎn)換并定義特定的輸出或節(jié)點的“activation”。
最簡單的激活函數(shù)被稱為線性激活,其中根本沒有應用任何轉(zhuǎn)換。 一個僅由線性激活函數(shù)組成的網(wǎng)絡很容易訓練,但不能學習復雜的映射函數(shù)。線性激活函數(shù)仍然用于預測一個數(shù)量的網(wǎng)絡的輸出層(例如回歸問題)。
非線性激活函數(shù)是更好的,因為它們允許節(jié)點在數(shù)據(jù)中學習更復雜的結(jié)構 。兩個廣泛使用的非線性激活函數(shù)是sigmoid 函數(shù)和雙曲正切 激活函數(shù)。
Sigmoid 激活函數(shù) ,也被稱為 Logistic函數(shù)神經(jīng)網(wǎng)絡,傳統(tǒng)上是一個非常受歡迎的神經(jīng)網(wǎng)絡激活函數(shù)。函數(shù)的輸入被轉(zhuǎn)換成介于0.0和1.0之間的值。大于1.0的輸入被轉(zhuǎn)換為值1.0,同樣,小于0.0的值被折斷為0.0。所有可能的輸入函數(shù)的形狀都是從0到0.5到1.0的 s 形。在很長一段時間里,直到20世紀90年代早期,這是神經(jīng)網(wǎng)絡的默認激活方式。
雙曲正切函數(shù) ,簡稱 tanh,是一個形狀類似的非線性激活函數(shù),輸出值介于-1.0和1.0之間。在20世紀90年代后期和21世紀初期,由于使用 tanh 函數(shù)的模型更容易訓練,而且往往具有更好的預測性能,因此 tanh 函數(shù)比 Sigmoid激活函數(shù)更受青睞。
Sigmoid和 tanh 函數(shù)的一個普遍問題是它們值域飽和了 。這意味著,大值突然變?yōu)?.0,小值突然變?yōu)?-1或0。此外,函數(shù)只對其輸入中間點周圍的變化非常敏感。
無論作為輸入的節(jié)點所提供的求和激活是否包含有用信息,函數(shù)的靈敏度和飽和度都是有限的。一旦達到飽和狀態(tài),學習算法就需要不斷調(diào)整權值以提高模型的性能。
最后,隨著硬件能力的提高,通過 gpu 的非常深的神經(jīng)網(wǎng)絡使用Sigmoid 和 tanh 激活函數(shù)不容易訓練。在大型網(wǎng)絡深層使用這些非線性激活函數(shù)不能接收有用的梯度信息。錯誤通過網(wǎng)絡傳播回來,并用于更新權重。每增加一層,錯誤數(shù)量就會大大減少。這就是所謂的消失梯度 問題,它能有效地阻止深層(多層)網(wǎng)絡的學習。
雖然非線性激活函數(shù)的使用允許神經(jīng)網(wǎng)絡學習復雜的映射函數(shù),但它們有效地阻止了學習算法與深度網(wǎng)絡的工作。在2000年代后期和2010年代初期,通過使用諸如波爾茲曼機器和分層訓練或無監(jiān)督的預訓練等替代網(wǎng)絡類型,這才找到了解決辦法。
2. ReLU(Rectified Linear Activation Function)
為了訓練深層神經(jīng)網(wǎng)絡,需要一個激活函數(shù)神經(jīng)網(wǎng)絡,它看起來和行為都像一個線性函數(shù),但實際上是一個非線性函數(shù),允許學習數(shù)據(jù)中的復雜關系 。該函數(shù)還必須提供更靈敏的激活和輸入,避免飽和。
因此,ReLU出現(xiàn)了,采用 ReLU 可以是深度學習革命中為數(shù)不多的里程碑之一 。ReLU激活函數(shù)是一個簡單的計算,如果輸入大于0,直接返回作為輸入提供的值;如果輸入是0或更小,返回值0。
我們可以用一個簡單的 if-statement 來描述這個問題,如下所示:
if?input?>?0:
??return?input
else:
??return?0
對于大于零的值,這個函數(shù)是線性的,這意味著當使用反向傳播訓練神經(jīng)網(wǎng)絡時,它具有很多線性激活函數(shù)的理想特性。然而,它是一個非線性函數(shù),因為負值總是作為零輸出。由于矯正函數(shù)在輸入域的一半是線性的,另一半是非線性的,所以它被稱為分段線性函數(shù)(piecewise linear function ) 。
3. 如何實現(xiàn)ReLU
我們可以很容易地在 Python 中實現(xiàn)ReLU激活函數(shù)。
#?rectified?linear?function
def?rectified(x):
??return?max(0.0,?x)
我們希望任何正值都能不變地返回,而0.0或負值的輸入值將作為0.0返回。
下面是一些修正的線性激活函數(shù)的輸入和輸出的例子:
#?demonstrate?the?rectified?linear?function
#?rectified?linear?function
def?rectified(x):
??return?max(0.0,?x)
#?demonstrate?with?a?positive?input
x?=?1.0
print('rectified(%.1f)?is?%.1f'?%?(x,?rectified(x)))
x?=?1000.0
print('rectified(%.1f)?is?%.1f'?%?(x,?rectified(x)))
#?demonstrate?with?a?zero?input
x?=?0.0
print('rectified(%.1f)?is?%.1f'?%?(x,?rectified(x)))
#?demonstrate?with?a?negative?input
x?=?-1.0
print('rectified(%.1f)?is?%.1f'?%?(x,?rectified(x)))
x?=?-1000.0
print('rectified(%.1f)?is?%.1f'?%?(x,?rectified(x)))
輸出如下:
rectified(1.0)?is?1.0
rectified(1000.0)?is?1000.0
rectified(0.0)?is?0.0
rectified(-1.0)?is?0.0
rectified(-1000.0)?is?0.0
我們可以通過繪制一系列的輸入和計算出的輸出,得到函數(shù)的輸入和輸出之間的關系。下面的示例生成一系列從 -10到10的整數(shù),并計算每個輸入的校正線性激活,然后繪制結(jié)果。
#?plot?inputs?and?outputs
from?matplotlib?import?pyplot
#?rectified?linear?function
def?rectified(x):
??return?max(0.0,?x)
#?define?a?series?of?inputs
series_in?=?[x?for?x?in?range(-10,?11)]
#?calculate?outputs?for?our?inputs
series_out?=?[rectified(x)?for?x?in?series_in]
#?line?plot?of?raw?inputs?to?rectified?outputs
pyplot.plot(series_in,?series_out)
pyplot.show()
運行這個例子會創(chuàng)建一個圖,顯示所有負值和零輸入都突變?yōu)?.0,而正輸出則返回原樣:

ReLU函數(shù)的導數(shù)是斜率。負值的斜率為0.0,正值的斜率為1.0。
傳統(tǒng)上,神經(jīng)網(wǎng)絡領域已經(jīng)不能是任何不完全可微的激活函數(shù),而ReLU是一個分段函數(shù)。從技術上講,當輸入為0.0時,我們不能計算ReLU的導數(shù),但是,我們可以假設它為0。
4. ReLU的優(yōu)點
4.1. ?計算簡單性
tanh 和 sigmoid 激活函數(shù)需要使用指數(shù)計算, 而ReLU只需要max(),因此他計算上更簡單,計算成本也更低 。
4.2. ?代表性稀疏
ReLU的一個重要好處是,它能夠輸出一個真正的零值 。這與 tanh 和 sigmoid 激活函數(shù)不同,后者學習近似于零輸出,例如一個非常接近于零的值,但不是真正的零值。這意味著負輸入可以輸出真零值,允許神經(jīng)網(wǎng)絡中的隱層激活包含一個或多個真零值。這就是所謂的稀疏表示,是一個理想的性質(zhì),在表示學習,因為它可以加速學習和簡化模型。
4.3. 線性行為
ReLU看起來更像一個線性函數(shù),一般來說,當神經(jīng)網(wǎng)絡的行為是線性或接近線性時,它更容易優(yōu)化 。
這個特性的關鍵在于,使用這個激活函數(shù)進行訓練的網(wǎng)絡幾乎完全避免了梯度消失的問題,因為梯度仍然與節(jié)點激活成正比。
4.4. 訓練深度網(wǎng)絡
ReLU的出現(xiàn)使得利用硬件的提升和使用反向傳播成功訓練具有非線性激活函數(shù)的深層多層網(wǎng)絡成為可能 。
5. 使用ReLU的技巧
5.1. 使用 ReLU 作為默認激活函數(shù)
很長一段時間,默認的激活方式是Sigmoid激活函數(shù)。后來,Tanh成了激活函數(shù)。對于現(xiàn)代的深度學習神經(jīng)網(wǎng)絡,默認的激活函數(shù)是ReLU激活函數(shù) 。
5.2. 對 MLPs,CNNs 使用 ReLU,但不是 RNNs
ReLU 可以用于大多數(shù)類型的神經(jīng)網(wǎng)絡,它通常作為多層感知機神經(jīng)網(wǎng)絡和卷積神經(jīng)網(wǎng)絡的激活函數(shù) ,并且也得到了許多論文的證實。傳統(tǒng)上,LSTMs 使用 tanh 激活函數(shù)來激活cell狀態(tài),使用 Sigmoid激活函數(shù)作為node輸出。而ReLU通常不適合RNN類型網(wǎng)絡的使用。
5.3. 嘗試更小的bias輸入值
偏置是節(jié)點上具有固定值的輸入,這種偏置會影響激活函數(shù)的偏移,傳統(tǒng)的做法是將偏置輸入值設置為1.0。當在網(wǎng)絡中使用 ReLU 時,可以將偏差設置為一個小值,例如0.1 。
5.4. 使用“He Weight Initialization”
在訓練神經(jīng)網(wǎng)絡之前,網(wǎng)絡的權值必須初始化為小的隨機值。當在網(wǎng)絡中使用 ReLU 并將權重初始化為以零為中心的小型隨機值時,默認情況下,網(wǎng)絡中一半的單元將輸出零值。有許多啟發(fā)式方法來初始化神經(jīng)網(wǎng)絡的權值,但是沒有最佳權值初始化方案。何愷明的文章指出Xavier 初始化和其他方案不適合于 ReLU ,對 Xavier 初始化進行一個小的修改,使其適合于 ReLU,提出He Weight Initialization,這個方法更適用于ReLU 。
5.5. ?縮放輸入數(shù)據(jù)
在使用神經(jīng)網(wǎng)絡之前對輸入數(shù)據(jù)進行縮放是一個很好的做法。這可能涉及標準化變量,使其具有零均值和單位方差,或者將每個值歸一化為0到1。如果不對許多問題進行數(shù)據(jù)縮放,神經(jīng)網(wǎng)絡的權重可能會增大,從而使網(wǎng)絡不穩(wěn)定并增加泛化誤差。無論是否在網(wǎng)絡中使用 ReLU,這種縮放輸入的良好實踐都適用。
5.6. 使用懲罰權重
ReLU 的輸出在正域上是無界的。這意味著在某些情況下,輸出可以繼續(xù)增長。因此,使用某種形式的權重正則化可能是一個比較好的方法,比如 l1或 l2向量范數(shù)。這對于提高模型的稀疏表示(例如使用 l 1正則化)和降低泛化誤差都是一個很好的方法 。
長按掃描下方二維碼添加小助手。
可以一起討論遇到的問題
聲明:轉(zhuǎn)載請說明出處
掃描下方二維碼關注【集智書童】公眾號,獲取更多實踐項目源碼和論文解讀,非常期待你我的相遇,讓我們以夢為馬,砥礪前行!

