前面發佈的文章介紹了感知機,瞭解了感知機可以通過疊加層表示複雜的函數。遺憾的是,設定合適的、能符合預期的輸入與輸出的權重,是由人工進行的。從本章開始,將進入神經網絡的學習,首先介紹激活函數,因爲它是連接感知機和神經網絡的橋樑。如果讀者認知閱讀了本專題知識,相信你必有收穫。
感知機數學表達式的簡化
前面我們介紹了用感知機接收兩個輸入信號的數學表示如下:
現在將上式改成更加簡潔的形式,我們不妨想一下,上面的表達式(或者說是函數)輸出y只有兩種值0和1。因此,我們引入一個新函數將上式改寫成下式:
式(2)中,輸入信號的總和會被函數h(x)轉換,轉換後的值就是輸出y。而式(3)所表示的h(x)在輸入超過0時返回1,否則返回0。不難理解,式(1)和式(2)、(3)做的是一件事情。其實這和數學中的複合函數的意思一樣(將b+w1x1+w2x2整體作爲變量x,變量名可隨便取)。
激活函數登場
我們剛引入的h(x)函數能將輸入信號的總和轉換爲輸出信號(只有0和1),這種函數就是激活函數。正如“激活”二字,激活函數就是決定如何來激活輸入信號的總和。讀者意識可能有點模糊,我們對上面的式子再分析一下,將式(2)分爲兩個階段,如下式,第一階段是計算輸入信號的加權和,第二階段則用激活函數來轉換這一加權和。
式(4)計算輸入信號和偏置b的總和,記爲a,接着用h()函數將a轉換爲輸出y。這裏我們用下圖來形象地表示式(4)和式(5)。
0表示神經元,這裏我們新增了一個輸入信號爲常數1的神經元(灰色),其權重爲b,主要是把偏置b(控制神經元被激活的容易程度)添加至感知機中。把上圖和上面的公式結合起來分析,節點a接收了輸入信號的加權和,接着節點a被激活函數h()轉換爲節點y輸出。注意節點和神經元是一樣的意思。
試想什麼樣的函數的輸出只有0和1兩種值,毫無疑問,階躍函數(在0處突變爲1)的輸出就是這樣的。這裏科普一下,一般而言,單層感知機也稱爲樸素感知機,即使用了階躍函數作爲激活函數的單層網絡。多層感知機指神經網絡,即使用了sigmoid函數等平滑函數作爲激活函數的多層網絡。
式(3)表明,輸入一旦超過閥值,激活函數就切換輸出,因此在感知機中的激活函數是“階躍函數”。我們不難發問,如果感知機使用其他函數作爲激活函數,結果會怎麼樣呢?答案是使用其他激活函數,那我們就進入了神經網絡的世界了。下面我們詳細介紹在神經網絡中常用的幾種激活函數。
階躍函數
如式(3),輸入大於0,輸出爲1,否則輸出爲0。Python實現如下:
import numpy as np
import matplotlib.pylab as plt
"""numpy輕易實現"""
def step_function(x):
return np.array(x>0,dtype=np.int) #true爲1,false爲0
"""繪圖"""
x=np.arange(-3.0,3.0,0.1)
y=step_function(x)
plt.plot(x,y)
plt.ylim(-0.1,1.1)
plt.show()
sigmoid函數
在神經網絡中,sigmoid函數常作爲激活函數,其表達式如下:
式(6)中exp(-x)表示e-x次方的意思。實際上,感知機和神經網絡的主要區別就在於激活函數的不同。Sigmoid函數作爲激活函數,對信號進行轉換,轉換後的信號被傳送給下一個神經元。Python實現如下:
"""sigmoid函數,除了函數不一樣,繪圖代碼同上"""
def sigmoid(x):
return 1/(1+np.exp(-x)) #numpy的廣播功能
比較
繪圖代碼如下:
# coding: utf-8
#階躍函數和sigmoid函數比較
import numpy as np
import matplotlib.pylab as plt
def sigmoid(x):
return 1 / (1 + np.exp(-x))
def step_function(x):
return np.array(x > 0, dtype=np.int)
x = np.arange(-5.0, 5.0, 0.1)
y1 = sigmoid(x)
y2 = step_function(x)
plt.plot(x, y1)
plt.plot(x, y2, 'k--')
plt.ylim(-0.1, 1.1) #指定圖中繪製的y軸的範圍
plt.show()
不同點:
(1)sigmoid函數是一條平滑的曲線,即輸出隨輸入發生連續的變化,階躍函數以0爲界,發生急劇性的變化。sigmoid函數的平滑性對神經網絡的學習極有幫助。
(2)階躍函數只能輸出0或1(二元信號),而sigmoid函數可輸出連續的實數信號。
相同點:
(1)形狀相似,輸入小時,輸出接近0;輸入增大時,輸出向1靠近。也就是說,當輸入信號爲重要信息時,階躍函數和sigmoid函數都會輸出較大的值;當輸入信號爲不重要的信息時,兩者都輸出較小的值。
(2)輸出信號值均在0~1之間。
(3)兩者都是非線性函數。階躍函數是一條折線,sigmoid函數是一條曲線。實際上,神經網絡的激活函數必須使用非線性函數,否則加深層的意義就沒有了。對於線性函數而言,不管如何加深層,總存在與之等效的無隱藏層的神經網絡。舉個例子,激活函數h(x)=cx,把y(x)=h(h(x))的運算對應2層神經網絡,顯然y(x)=c·c·x=c2·x=ax(a= c2)。所以爲了利用多層神經網絡的優勢,激活函數必須使用非線性函數。
Relu函數
Sigmoid函數的使用歷史比較久,現在主要流行ReLU(Rectified Linear Unit)函數,如下:
式(7)表明,輸入大於0,則直接輸出該值;輸入小於等於0時,輸出0。Python實現也很簡單,代碼如下:
# 只給出函數,繪圖代碼同上
def relu(x):
return np.maximum(0, x) #小於0的爲0,大於0的爲其本身
本章剩餘部分的內容一直採用sigmoid函數作爲激活函數,在靠後的知識點中,才使用ReLU函數。
今天的內容就講到這裏了,希望讀者好好回顧一下激活函數的產生及特點。下一篇知識點,將介紹使用numpy數組實現神經網絡。歡迎讀者訂閱我的微信公衆號“Python生態智聯”,充分利用好零碎時間學AI