人工智慧---神經網路啟用函式恆等函式、sigmoid函式、softmax函式詳解

Foxerity 發表於 2020-11-20
人工智慧 神經網路

系列文章目錄

人工智慧—深度學習神經網路神經元的實現
人工智慧–深度學習兩層全連線神經網路搭建



前言

      我們在上一章節中已經實現了神經網路系統的結構,但作為一個成熟的預測或者分類神經網路,他還需要一定的完善。今天我們將詳細介紹的就是其中的輸出層中的一些優化。


一、輸出層的意義

      我們前面提到過,神經網路是一種為了輔助深度學習的工具方法,而深度學習又是完善機器學習的一個分支,所以說本質上深度學習神經網路的覆蓋問題往往都是機器學習的問題,而機器學習的問題根據結果的不同,就能分為迴歸問題和分類問題。那神經網路中又是如何體現這個迴歸或者分類的目的的呢?那肯定是要看我們的輸出層的結果形式。
      在上一章中,我們執行了自己的第一個神經網路系統,得出了一個結果,但在沒有具體背景的情況下,那個結果其實沒有什麼意義,而我們要想使這個結果有意義,記得憑藉我們的輸出層啟用函式了。
      當我們的背景問題是一個迴歸問題的時候,我們往往選擇恆等啟用函式,也就是不對輸出做任何改變,因為迴歸問題往往最後計算的結果是一個具體的權重,也是我們的最終答案,那我們當然是原封不動的輸出是最好的。
      當我們的背景問題是一個分類問題的時候,輸出結果往往是一個概率,不同結點的值代表了是這個分類的概率大小,但由於複雜的網路關係,最後的值往往不能約束在 [ 0 , 1 ] [0,1] [0,1]範圍內,為了讓他更加貼切概率的概念,我們會選擇使用前面提到的sigmoid函式或者今天我們要著重介紹的softmax函式

二、不同啟用函式的介紹和實現

1.恆等函式

      恆等函式主要用於對迴歸問題的啟用,這種問題中往往需要我們最大程度的保護最後的輸出結果,所以恆等函式簡單點來說那就是什麼都不做。他的定義為:
y = x y=x y=x

2.sigmoid函式

      sigmoid函式由於其限制在 [ 0 , 1 ] [0,1] [0,1]中的特性,所以很適合用來做概率轉換函式。他的定義我們已經很熟悉:
1 1 + e − x \frac{1}{1+e^{-x}} 1+ex1

3.softmax函式

      相比較sigmoid函式他比較適合於二分類問題,softmax函式能充分考慮每一個輸出結點的權重影響,從而使概率的描述更加準確。他的定義式為:
e a k ∑ i = 1 n e a i \frac{e^{a_{k}}}{\sum_{i=1}^ne^{a_{i}}} i=1neaieak

4.softmax函式的問題

      因為softmax中不乏指數運算,而指數運算最大的問題就是容易產生特別大的數,而當兩個數特別大時,再進行其他操作就很容易出錯,比如公式裡的除法。讓我們來看個例子具體感受一下。

def softmax(x):
    return np.exp(x)/np.sum(np.exp(x))

x = np.array([1000,1010,1020])
y = softmax(x)
print(y)

輸出結果為:

[nan nan nan]

Process finished with exit code 0

這種現象就是叫做計算機中的“溢位”,而我們如何避免過大的值導致的運算過程“溢位”呢?
於是我們引入了一個常量,將softmax函式改進為:
C e a k C ∑ i = 1 n e a i \frac{Ce^{a_{k}}}{C\sum_{i=1}^{n}e^{a_{i}}} Ci=1neaiCeak
因為分式上下乘以一個常量,所以分式的值不會改變然後我們再進行變形:
C e a k C ∑ i = 1 n e a i = e a k + log ⁡ c ∑ i = 1 n e a i + log ⁡ c = e a k + C ′ ∑ i = 1 n e a k + C ′ \frac{Ce^{a_{k}}}{C\sum_{i=1}^{n}e^{a_{i}}}=\frac{e^{a_{k}+\log{c}}}{\sum_{i=1}^{n}e^{a_i+\log{c}}}=\frac{e^{a_k+C^{'}}}{\sum_{i=1}^ne^{a_k+C^{'}}} Ci=1neaiCeak=i=1neai+logceak+logc=i=1neak+Ceak+C
轉換成這個形式,那就可以對 C ′ C' C進行任意取值,因為C是任意的,所以 C ′ C' C也相應的是,但我們引入這個 C ′ C' C的最終目的是為了防止溢位,所以建議這個 C ′ C' C取最大值的負數。也就是
e a k − max ⁡ ( a ) ∑ i = 1 n e a i − max ⁡ ( a ) \frac{e^{a_{k}-\max(a)}}{\sum_{i=1}^ne^{a_{i}-\max(a)}} i=1neaimax(a)eakmax(a)
還是代入到那個例子中進行實驗:

def softmax(x):
    return np.exp(x-np.max(x))/np.sum(np.exp(x-np.max(x)))

x = np.array([1000,1010,1020])
y = softmax(x)
print(y)

輸出結果為:

[2.06106005e-09 4.53978686e-05 9.99954600e-01]

Process finished with exit code 0

很明顯我們可以看到,原來為nan的異常值已經可以被正確的計算了!

三、將softmax函式引入我們的輸出層

      還是以我們之前實現的神經網路系統為例,我們將最後的輸出層啟用函式置換為我們剛剛實現的softmax函式來再看看是否能準確執行!

程式碼如下(示例):

def softmax(x):
    return np.exp(x-np.max(x))/np.sum(np.exp(x-np.max(x)))
def forward_net(network,x):
    W1 = network['W1']
    b1 = network['b1']
    W2 = network['W2']
    b2 = network['b2']
    W3 = network['W3']
    b3 = network['b3']
    x = np.dot(x,W1)+b1
    x = ReLU(x)
    x = np.dot(x,W2)+b2
    x = ReLU(x)
    x = np.dot(x, W3) + b3
    x = softmax(x)
    return x

執行結果為:

[0.00196166 0.99803834]

Process finished with exit code 0

看來我們的啟用函式已經能完美執行啦。


總結

      為了能更好的帶領大家投入到真實的神經網路執行例項中去,筆者準備了這一章,讓大家能更好的認識一種最常用的輸出層啟用函式——softmax。接下來我們就可以自如的使用哦我們的網路進入到各種各樣的場景中去了

相關文章