深度學習基礎算法-神經網絡之激活函數

神經網絡算法

神經網絡算法試圖模擬生物神經系統的學習過程,以此實現強大的預測性能。不過由於是模仿人類大腦,所以神經網絡的模型複雜度很高也是衆所周知。在現實應用中,神經網絡可以說是解釋性最差的模型之一,商業環境中很少使用神經網絡。然而除了商業分析,還有許多算法應用的部分,其中最重要的是深度學習和人工智能的領域,現在大部分已經成熟的人工智能技術:圖像識別,語音識別等等,背後都是基於神經網絡的深度學習算法。因此,作爲機器學習中(可能是)最複雜的,深度學習中基礎的算法,神經網絡的瞭解和學習是很有必要的。

從感知機到神經網絡

神經網絡與多層感知機還是有一點區別的。用圖來表示神經網絡的話,如下圖所示。我們把最左邊的一列稱爲輸入層,最右邊的一列稱爲輸出層,中間的一列稱爲中間層(有的教材也稱爲隱藏層)。所謂"隱藏"的意思,在這裏面的神經元我們是看不見的。我們把下圖的三層依次稱爲第0層,第1層,第2層,分別對應輸入層,中間層,輸出層。
在這裏插入圖片描述
單就神經網絡的這種連接方式,和之前的感知機是沒有任何差別的。感知機的公式:
在這裏插入圖片描述
在之前的圖片中,偏置 並沒有在圖像中顯示出來,我們可以把圖片改成下圖來表示權重 ,它對應的輸入信號固定爲1。
在這裏插入圖片描述
這個感知機將x1 、x2、1 三個信號作爲神經元的輸入,將其和各自的權重相乘後,傳送至下一個神經元。在下一個神經元中,計算這些加權信號的總和。如果這個總和超過0,則輸出1,否則輸出0。而偏置部分的信號始終是1,是不變的。現在,我們爲了能夠進一步簡化公式,爲之後使用線性代數計算更方便,我們把公式再一次進行改造:
y=h(b+ω1x1 +ω2x2)y=h(b+ω_1x_1~+ω_2x_2)
而h(x)就應該是這樣的:
h(x)={0x01x0h(x)=\left\{ \begin{array}{ll} 0 & x \leqslant 0\\1 & x \geqslant 0 \end{array} \right.
輸入信號的總和會被函數h(x)轉換,轉換後的值就是輸出y。這樣一來我們就把之前的公式拆分成兩個更簡單的模式了。在感知機中,h(x) 這個函數的形式非常簡單,就是當輸入總和不超過0的時候,輸出0,而輸入總和超過0的時候,就輸出1。這種h(x)函數,我們叫做階躍函數,使用這種算法的感知機一般叫做"樸素感知機"。
但是,在神經網絡也就是"多層感知機中"中,我們通常不會採用這麼簡單的函數,而會使用更復雜一些的 h(x) 決定到底是輸出0還是1。

激活函數

我們爲什麼要費勁把公式拆分上上面的那種形式呢,就是爲了激活函數的登場在做鋪墊。h(x) 這個函數,會將輸入信號的總和轉換爲輸出信號(0或者1),我們把這種函數稱爲激活函數(activation function)。激活的意思就是,使用這個函數來判斷,當輸入進行的總和達到什麼程度的時候才予以輸出。
我們把剛纔的感知機公式,再一次進行改造。因爲h(x) 可以是其他的形式:

a=b+ω1x1 +ω2x2y=h(a)a=b+ω_1x_1~+ω_2x_2\\ y=h(a)
首先,計算加權輸入信號和偏置的總和,記爲a。然後,用h(x)函數將a轉換爲輸出y。如果我們想要在圖中明確表示出上面兩個公式的表示過程,可以把圖片變成這樣.
在這裏插入圖片描述
首先,計算加權輸入信號和偏置的總和,記爲a。然後,用h(x)函數將a轉換爲輸出y。如果我們想要在圖中明確表示出上面兩個公式的表示過程,可以把圖片變成這樣.
信號的加權總和爲節點a,然後節點a被激活函數h()轉換成節點y。這裏所說的"節點",和之前所說的"神經元"含義相同。
那麼常用的激活函數有哪些呢?下面我們一起來看一下:
在這裏插入圖片描述

sigmoid函數

sigmoid函數是神經網絡中最常使用的一個激活函數,如果學過邏輯迴歸的同學應該知道,在邏輯迴歸中我們也是使用這個函數去進行分類的。sigmoid函數的公式爲:
在這裏插入圖片描述
這裏的e是自然常數,值約爲2.71828。向sigmoid函數輸入某個數值後,例如5,8,3.4 等,sigmoid函數就會對應的輸出一個值.
具體的結果,我們可以先畫出sigmoid函數的圖像.

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline
# sigmoid函數
def sigmoid(x):
    h = 1/(1+np.exp(-x))
    return h
# 繪製 sigmoid函數曲線
x = np.arange(-10,10,0.1)
y = sigmoid(x)

plt.figure(figsize = (8,6),dpi=60)
plt.plot(x,y,c='blue',alpha=0.8,linewidth=2,label='Sigmoid line')
plt.ylim(-0.1,1.1)
plt.xlim(-11,11)
plt.yticks(np.arange(0,1.1,0.1),fontsize=12)
plt.xticks(np.arange(-10,11,2),fontsize=12)
plt.title('Sigmoid line Plot',color='k',fontsize=15)
plt.grid(linestyle='-.',alpha=0.4)
plt.legend(loc=2,frameon=False,fontsize=12)
plt.show()

在這裏插入圖片描述
觀察圖形可以看到,sigmoid函數是一條平滑的,在0-1之間變化的曲線。爲了說明sigmoid函數有什麼樣的好處,我們用感知機中的階躍函數和sigmoid函數進行對比.

階躍函數的實現

首先我們用Python實現這個函數的功能:

def step_function(x):
    if x > 0:
        return 1
    else:
        return 0
step_function(1)
1

如果輸入的是Ndarray數組,則可以這樣實現:

# 使用numpy實現階躍函數
def step_function(x):
    y = x > 0                #生成布爾序列
    return y.astype(np.int)  #把布爾序列轉換成1和 0     

對於這個函數,當我們傳輸一些數組的時候,會一次生成階躍函數的正確結果

x = np.array([-1,1,2])
step_function(x)
array([0, 1, 1])
#比如:
np.array([True,False]).astype(np.int)
array([1, 0])

我們也可以畫出階躍函數的圖像:

# 繪製階躍函數圖形
x = np.arange(-5,5,0.01)
y = step_function(x)
plt.plot(x,y);

在這裏插入圖片描述
階躍函數以0爲界,輸出從0切換爲1(或者從1切換爲0),它的值呈階梯式變化,所以稱爲階躍函數。

sigmoid函數和階躍函數的比較

首先,最明顯的是函數的平滑性不同,sigmoid是一條平滑連續的曲線,而階躍函數以0爲界,在這裏輸出發生根本性變化。而神經網絡的學習,我們需要的不是非此即彼的變化,而是平滑的變化形式,因此sigmoid函數這種平滑的特點對於神經網絡具有重要意義。
在這裏插入圖片描述
另一個不同點是,相對於階躍函數只能返回0或1,sigmoid函數可以返回0.731 . . . 、0.880 . . . 等實數,當然這也是由平滑性決定的,如果神經網絡中傳遞的信號,只有0和1的話,毫無疑問,這個網絡的變化就太簡單了,而sigmoid函數這種形式可以保證模型足夠複雜的變化。也就是說,感知機中神經元之間流動的是0或1的二元信號,而神經網絡中流動的是連續的實數值信號。
如果把這兩個函數與水聯繫起來,則階躍函數可以比作“竹筒敲石”,sigmoid函數可以比作“水車”。階躍函數就像竹筒敲石一樣,只做是否傳送水(0或1)兩個動作,而sigmoid函數就像水車一樣,根據流過來的水量相應地調整傳送出去的水量。
階躍函數和sigmoid函數之間也是有共同點的:從圖像上可以看出來,兩者都是在0和1之間進行變化,當輸入小的時候,輸出爲0或者接近0,當輸入增大,輸出就變成1或者接近1。也就是說,當輸入信號爲重要信息時,階躍函數和sigmoid函數都會輸出較大的值;當輸入信號爲不重要的信息時,兩者都輸出較小的值。還有一個共同點是,不管輸入信號有多小,或者有多大,輸出信號的值都在0到1之間。

非線性函數

階躍函數和sigmoid函數還有其他共同點,就是兩者均爲非線性函數。sigmoid函數是一條曲線,階躍函數是一條像階梯一樣的折線,兩者都屬於非線性的函數。神經網絡的激活函數必須使用非線性函數。換句話說,激活函數不能使用線性函數。爲什麼不能使用線性函數呢?因爲使用線性函數的話,加深神經網絡的層數就沒有意義了!
爲了具體地(稍微直觀地)理解這一點,我們來思考下面這個簡單的例子:把線性函數h(x) = cx作爲激活函數,把y(x) = h(h(h(x)))的運算對應3層神經網絡,則
y(x)=h(h(h(x)))=cccx=3cxα=3cy(x)=αxy(x) =h(h(h(x)))\\=c*c*cx\\ =3cx\\ 令α=3c,則有:\\ y(x)=αx

由於α和c都是常數,所以y(x)=αx與h(x)=cx是完全等價的。也就是說,對於線性函數來說,不管如何加深層數,總是存在與之等效的“無隱藏層的神經網絡”。所以說,使用線性函數時,無法發揮多層網絡帶來的優勢。因此,爲了發揮疊加層所帶來的優勢,激活函數必須使用非線性函數。

ReLU 函數

作爲激活函數,sigmoid函數在神經網絡的發展歷史上很早被應用,但是現在來講,ReLU(Rectified Linear Unit) 修正線性單元函數應用會更加廣泛一些。
ReLU函數具有這樣的特性:輸入大於0時,直接輸出該值;在輸入小於等於0時,輸出0。ReLU的函數公式爲:
在這裏插入圖片描述
ReLU函數是一個非常簡單的函數,使用Python去實現的話,可以這樣寫:

def relu(x):
    y = np.maximum(0,x)#從輸入的數值中選擇較大的那個值輸出
    return y
relu(-5)
0

繪製relu函數的圖像:

# 繪製 relu函數
x = np.arange(-5,5,0.01)
y = np.maximum(0,x)
plt.plot(x,y);

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章