作者:Dishashree Gupta
翻譯:王紫岳
校對:王琦
本文約5200字,建議閱讀20分鐘
本文簡要介紹了作者在初次進行機器學習的操作時所遇到的情況與得到的教訓。
摘要本文最初發(fā)表于2017年10月,并于2020年1月進行了更新,增加了三個新的激活函數和python代碼。
引言今天,因特網提供了獲取大量信息的途徑。無論我們需要什么,只需要谷歌搜索一下即可。然而,當我們獲取了這么多的信息時,我們又面臨著如何區(qū)分相關和無關的信息的挑戰(zhàn)。
當我們的大腦被同時灌輸大量信息時,它會努力去理解這些信息并將其分為“有用的”和“不那么有用的”。對于神經網絡而言,我們需要類似的機制來將輸入的信息分為“有用的”或“不太有用的”。
這是網絡學習的重要方式,因為并不是所有的信息都同樣有用。它們中的一些僅僅是噪音,而這就是激活函數的用武之地了。激活函數幫助神經網絡使用重要信息,并抑制不相關的數據點。
接下來讓我們來看看這些激活函數,了解它們是如何工作的,并找出哪些激活函數適合于什么樣的問題情景。
目錄1. 神經網絡概述
2. 我們可以不使用激活函數么?
3. 常用的激活函數以及什么時候使用他們
4. 選擇正確的激活函數
1. 神經網絡概述在我深入研究激活函數的細節(jié)之前,讓我們先快速了解一下神經網絡的概念以及它們是如何工作的。神經網絡是一種非常強大的模仿人腦學習方式的機器學習機制。
大腦接收外界的刺激,對輸入進行處理,然后產生輸出。當任務變得復雜時,多個神經元形成一個復雜的網絡,相互傳遞信息。
人工神經網絡試圖模仿類似的行為。你下面看到的網絡是由相互連接的神經元構成的神經網絡。每個神經元的特征是其權重、偏置和激活函數。
輸入信息被輸入到輸入層,神經元使用權重和偏差對輸入進行線性變換。
x = (weight * input) + bias
之后,對上述結果應用一個激活函數。
最后,激活函數的輸出移動到下一個隱藏層,重復相同的過程。這種信息的前向移動稱為前向傳播。
如果生成的輸出與實際值相距甚遠怎么辦?利用前向傳播的輸出來計算誤差。根據這個誤差值,更新神經元的權值和偏差。這個過程稱為反向傳播。
注:要詳細理解正向傳播和反向傳播,您可以閱讀下面的文章:
Understanding and coding neural network from scratch
附鏈接:https://www.analyticsvidhya.com/blog/2017/05/neural-network-from-scratch-in-python-and-r/
2. 我們可以不使用激活函數么?我們知道,在正向傳播期間,使用激活函數會在每一層引入一個額外的步驟。現在我們的問題是,假如激活函數給神經網絡增加了復雜性,我們可以不使用激活函數嗎?
想象一個沒有激活函數的神經網絡。在這種情況下,每個神經元只會利用權重和偏差對輸入信息進行線性變換。雖然線性變換使神經網絡更簡單,但這個網絡的功能會變得更弱,并無法從數據中學習復雜的模式。
沒有激活函數的神經網絡本質上只是一個線性回歸模型。
因此,我們對神經元的輸入進行非線性變換,而神經網絡中的這種非線性是由激活函數引入的。
在下一節(jié)中,我們將研究不同類型的激活函數、它們的數學公式、圖形表示和python代碼。
3. 常用的激活函數以及什么時候使用他們當我們有一個激活函數時,首先想到的是一個基于閾值的分類器,即神經元是否應該根據線性變換的值被激活。
換句話說,如果激活函數的輸入大于閾值,則神經元被激活,否則它就會失效,即它的輸出不考慮下一個隱含層。讓我們從數學的角度來看。
f(x) = 1, x>=0 = 0, x<0
這是最簡單的激活函數,可以用python中的一個if-else判斷來實現
def binary_step(x): if x<0: return 0 else: return 1binary_step(5), binary_step(-1)
輸出:
(5,0)
在創(chuàng)建二分類器時,可以將二二元階躍函數用作激活函數。可以想象,當目標變量中有多個類時,這個函數將會失效。這就是二元階躍函數的局限性之一。
此外,階躍函數的梯度為零,在反向傳播過程中造成了障礙。也就是說,如果計算f(x)關于x的導數,結果是0。
f'(x) = 0, for all x
反向傳播過程中的權重和偏差是通過計算梯度來更新的。因為函數的梯度是零,所以權值和偏差不會更新。
在上面,我們看到了階躍函數的問題是函數的梯度變成了0。這是由于在二元階躍函數中沒有x的分量,因此我們可以用線性函數代替二元函數。我們可以把這個函數定義為:
f(x)=ax
這里的活性值(activation)與輸入成正比。本例中的變量“a”可以是任何常數值。讓我們快速定義python中的函數:
def linear_function(x):return 4*x linear_function(4), linear_function(-2)
輸出:
(16, -8)
你認為這種情況下的導數是什么呢?當我們對函數關于x求導時,得到的結果將是x的系數,而這個系數是一個常數。
f'(x) = a
雖然這里的梯度不為零,但它是一個常數,與輸入值x無關。這意味著權值和偏差在反向傳播過程中會被更新,但更新因子是相同的。
在這種情況下,神經網絡并不能真正改善誤差,因為每次迭代的梯度是相同的。網絡將不能很好地訓練和從數據中捕獲復雜的模式。因此,線性函數可能是需要高度解釋能力的簡單任務的理想選擇。
我們要看的下一個激活函數是Sigmoid函數。它是應用最廣泛的非線性激活函數之一。Sigmoid將值轉換為0和1之間。這是sigmoid的數學表達式:
f(x) = 1/(1+e^-x)
這里值得注意的一點是,與二元階躍和線性函數不同,sigmoid是一個非線性函數。
這本質上意味著,當我有多個神經元以sigmoid激活函數作為它們的激活函數時,它們的輸出也是非線性的。下面是在python定義函數的python代碼:
import numpy as npdef sigmoid_function(x): z = (1/(1 + np.exp(-x))) return z sigmoid_function(7),sigmoid_function(-22)
輸出:
(0.9990889488055994, 2.7894680920908113e-10)
另外,正如你在上圖中看到的,這是一個光滑的s型函數,并且是連續(xù)可微的。這個函數的導數是(1-sigmoid(x))。讓我們來看看它的梯度圖。
f'(x) = 1-sigmoid(x)
梯度值在-3和3范圍內是顯著的,但在其他區(qū)域,圖形變得更平坦。這意味著對于大于3或小于-3的值,梯度非常小。當梯度值趨近于0時,網絡就不是真的在學習。
另外,sigmoid函數不是關于0對稱的。所以所有神經元的輸出都是相同的符號。這可以通過縮放sigmoid函數來解決,這正是tanh函數所做的。請讓我們繼續(xù)讀下去。
tanh函數與sigmoid函數非常相似。唯一不同的是它是關于原點對稱的。本例中值的范圍是從-1到1。因此,下一層的輸入并不總是相同的符號。tanh函數定義為:
tanh(x)=2sigmoid(2x)-1
為了使用python編寫代碼,讓我們簡化前面的表達式。
tanh(x) = 2sigmoid(2x)-1tanh(x) = 2/(1+e^(-2x)) -1
下面是它的python代碼:
def tanh_function(x): z = (2/(1 + np.exp(-2*x))) -1return z tanh_function(0.5), tanh_function(-1)
輸出:
(0.4621171572600098, -0.7615941559557646)
就像你看到的,值的范圍是-1到1。除此之外,tanh函數的其他性質都與sigmoid函數相同。與sigmoid相似,tanh函數在所有點上都是連續(xù)可微的。
我們來看看tanh函數的梯度。
與sigmoid函數相比,tanh函數的梯度更陡。你可能會好奇,我們如何決定選擇哪個激活函數。通常tanh比sigmoid函數更受歡迎,因為它是以0為中心的,而且梯度不受一定方向的限制。
ReLU函數是另一個在深度學習領域得到廣泛應用的非線性激活函數。ReLU表示線性整流單元(Rectified Linear Unit)。與其他激活函數相比,使用ReLU函數的主要優(yōu)點是它不會同時激活所有神經元。
這意味著只有當線性變換的輸出小于0時,神經元才會失效。下圖將幫助你更好地理解這一點:
f(x)=max(0,x)
對于負的輸入值,結果是零,這意味著神經元沒有被激活。由于只有一定數量的神經元被激活,ReLU函數的計算效率遠高于sigmoid和tanh函數。下面是ReLU的python函數:
def relu_function(x): if x<0: return 0 else: return x relu_function(7), relu_function(-7)
輸出:
(7, 0)
我們來看看ReLU函數的梯度。
f'(x) = 1, x>=0 = 0, x<0
如果你觀察圖形的負方向,你會注意到梯度值是零。由于這個原因,在反向傳播過程中,一些神經元的權重和偏差沒有更新。這可能會產生從未被激活的死亡神經元。這種情況可通過“泄漏”ReLU函數來處理。
Leaky ReLU函數只是ReLU函數的一個改進版本。如我們所見,對于ReLU函數,當x<0時,梯度為0,這將使該區(qū)域的神經元失活。
定義Leaky ReLU是為了解決這個問題。我們不把x的負值定義為0,而是定義為x的一個極小的線性分量,這里給出它的數學定義:
f(x)= 0.01x, x<0 = x, x>=0
通過這個小的修改,圖形左邊的梯度就變成了一個非零值。因此,我們將不再在那個區(qū)域遇到死亡的神經元。這是Leaky ReLU函數的導數:
f'(x) = 1, x>=0 =0.01, x<0
因為Leaky ReLU是ReLU的一個變體,所以python代碼可以通過一個小的修改來實現:
def leaky_relu_function(x): if x<0: return 0.01*x else: return x leaky_relu_function(7), leaky_relu_function(-7)
輸出:
(7, -0.07)
除了Leaky ReLU,還有一些其他的ReLU變體,最流行的是Parameterised ReLU函數和Exponential Liner Unit。
這是ReLU的另一個變體,旨在解決軸的左半部分的梯度為零的問題。顧名思義,參數化ReLU引入了一個新參數作為函數負部分的斜率。下面是如何修改ReLU函數以體現包含的斜率參數-
f(x) = x, x>=0 = ax, x<0
當a的值固定為0.01時,函數就變成了Leaky ReLU函數。然而,對于Parameterised ReLU函數,‘a’也是一個可訓練的參數。該網絡還學習了' a '的值,以便更快、更優(yōu)地收斂。
這個函數的導數和Leaky ReLu函數是一樣的,除了0.01的值會被替換成a的值。
f'(x) = 1, x>=0 = a, x<0
當使用Leaky ReLU函數仍然不能解決未激活神經元問題,相關信息無法成功傳遞到下一層時,我們就可以使用Parameterised ReLU函數。
指數化線性單元(簡稱ELU)也是線性整流單元(ReLU)的一種變體,它改變了函數負部分的斜率。與Leaky Relu和parametric Relu函數不同,ELU使用了Log曲線來代替直線定義函數的負數部分。它被定義為
f(x) = x, x>=0 = a(e^x-1), x<0
讓我們在python中定義這個函數:
def elu_function(x, a): if x<0: return a*(np.exp(x)-1) else: return x elu_function(5, 0.1),elu_function(-5, 0.1)
輸出:
(5, -0.09932620530009145)
ELU函數對于x大于0的值的導數是1,就像所有ReLU變體一樣。但對于x<0的值,導數是a.e ^x 。
f'(x) = x, x>=0 = a(e^x), x<0
Swish是一個不太為人所知的激活函數,它是由谷歌的研究人員發(fā)現的。Swish的計算效率與ReLU相當,并且在層次更深的模型上顯示出比ReLU更好的性能。swish的值從負無窮到正無窮。函數定義為-
f(x) = x*sigmoid(x)f(x) = x/(1-e^-x)
正如你所看到的,函數曲線是平滑且在所有點上都是可微的。這在模型優(yōu)化過程中是有幫助的,也是Swish被認為優(yōu)于Relu的原因之一。
關于這個函數的一個獨特的特征是,swich函數不是單調的。這意味著即使輸入值增加,函數值也可能減少。讓我們看看swish函數的python代碼:
def swish_function(x): return x/(1-np.exp(-x)) swish_function(-67), swish_function(4)
輸出:
(5.349885844610276e-28, 4.074629441455096)
Softmax函數通常被描述為多個sigmoid的組合。我們知道sigmoid返回0到1之間的值,可將函數值視為數據點屬于特定類的概率。因此,sigmoid被廣泛應用于二分類問題。
softmax函數可用于多類分類問題。這個函數返回屬于每個類的數據點的概率。這是相同的數學表達式:
在為一個多類問題構建神經網絡時,輸出層的神經元數量與目標中的類的數量相同。
例如,如果你有三個類,在輸出層會有三個神經元。假設神經元的輸出是[1.2,0.9,0.75]。
對這些值應用softmax函數,您將得到以下結果—[0.42,0.31,0.27]。這些值表示這些數據點屬于每個類的概率。值得注意的是,所有值的和為1。讓我們在python中編碼:
def softmax_function(x): z = np.exp(x) z_ = z/z.sum() return z_ softmax_function([0.8, 1.2, 3.1])
輸出:
softmax_function([1.2 , 0.9 , 0.75])
4.選擇正確的激活函數現在我們已經看到了這么多的激活函數,我們需要一些邏輯/啟示來了解在什么情況下應該使用哪個激活函數。好或壞的判斷并沒有經驗法則。
然而,根據問題的性質,我們可以做出更好的選擇,使網絡更容易、更快地收斂。
現在,是時候冒險嘗試一下其他真實的數據集了。那么你準備好接受挑戰(zhàn)了嗎?通過以下實踐問題加速你的深度學習之旅:
l Practice Problem: Identify the Apparels(見下面鏈接)
https://datahack.analyticsvidhya.com/contest/practice-problem-identify-the-apparels/?utm_source=fundamentals-deep-learning-activation-functions-when-to-use-them&utm_medium=blog
l Practice Problem: Identify the Digits(見下面鏈接)
https://datahack.analyticsvidhya.com/contest/practice-problem-identify-the-digits/?utm_source=fundamentals-deep-learning-activation-functions-when-to-use-them&utm_medium=blog
結語:在本文中,我討論了各種類型的激活函數,以及在使用它們時可能遇到的問題類型。我建議你先從ReLU函數開始,并隨著你慢慢深入時,探索其他函數。你還可以設計自己的激活函數,為你的神經網絡提供一個非線性組件。如果您使用了自己的激活函數并且效果非常好,請與我們分享,我們將很樂意將其納入列表。
原文鏈接:
https://www.analyticsvidhya.com/blog/2020/01/fundamentals-deep-learning-activation-functions-when-to-use-them/
原文標題:
Fundamentals of Deep Learning – Activation Functions and When to Use Them?
編輯:王菁
校對:林亦霖
譯者簡介
王紫岳,悉尼大學Data Science在讀研究生,在數據科學界努力奮斗的求知者。喜歡有挑戰(zhàn)性的工作與生活,喜歡與朋友們熱切交談,喜歡在獨處的時候讀書品茶。張弛有度,才能夠以最飽滿的熱情迎接有點忙碌的生活。
—完—
聯(lián)系客服