chapter3 神經(jīng)網(wǎng)絡(luò)
3.1 從感知機(jī)到神經(jīng)網(wǎng)絡(luò)
? 神經(jīng)網(wǎng)絡(luò)的一個(gè)重要性質(zhì)是它可以自動(dòng)地從數(shù)據(jù)中學(xué)習(xí)到合適的權(quán)重參數(shù), 是一個(gè)自動(dòng)尋找參數(shù)版的感知機(jī).
? 通過(guò)感知機(jī),好消息是即便是計(jì)算機(jī)進(jìn)行的復(fù)雜處理线衫,感知機(jī)(理論上)也可以將其表示出來(lái)摸袁。壞消息是蔑歌,設(shè)定權(quán)重的工作止潘,即確定合適的撑螺、能符合預(yù)期的輸入與輸出的權(quán)重梧油,現(xiàn)在還是由人工進(jìn)行的捂掰。而神經(jīng)網(wǎng)絡(luò)的出現(xiàn)就是為了解決這一問(wèn)題.
用圖來(lái)表示神經(jīng)網(wǎng)絡(luò)的話,如圖所示蔑穴。我們把最左邊的一列稱為輸入層,最右邊的一列稱為輸出層惧浴,中間的一列稱為中間層存和。中間層有時(shí)也稱為隱藏層。
3.2 激活函數(shù)
感知機(jī)的公式為 b + w1x1 + w2x2, 設(shè) a = b + w1x1 + w2x2 , y = h(a). 剛才登場(chǎng)的h(x)函數(shù)會(huì)將輸入信號(hào)的總和轉(zhuǎn)換為輸出信號(hào)衷旅,這種函數(shù)一般稱為激活函數(shù)(activation function).
下面捐腿,我們將仔細(xì)介紹激活函數(shù)。激活函數(shù)是連接感知機(jī)和神經(jīng)網(wǎng)絡(luò)的
橋梁芜茵。
3.2.1 階躍函數(shù)
“階躍函數(shù)”表示的激活函數(shù)以閾值為界叙量,一旦輸入超過(guò)閾值,就切換輸出.因此九串,可以說(shuō)感知機(jī)中使用了階躍函數(shù)作為激活函數(shù)绞佩。神經(jīng)網(wǎng)絡(luò)一般使用其他的激活函數(shù).
階躍函數(shù)的代碼實(shí)現(xiàn):
def step_function(x):
if x > 0:
return 1
else:
return 0
由于后面要使用numpy 數(shù)組操作,可以將代碼優(yōu)化為
"""
這里,數(shù)組x中大于0的元素被轉(zhuǎn)換為True猪钮,小于等于0的元素被轉(zhuǎn)換為False品山,從而生成一個(gè)新的數(shù)組y。
數(shù)組y是一個(gè)布爾型數(shù)組烤低,但是我們想要的階躍函數(shù)是會(huì)輸出int型的0 或1的函數(shù)肘交。因此,需要把數(shù)組y的元素類型從布爾型轉(zhuǎn)換為int型扑馁。
"""
import numpy as np
def step_function(x):
return np.array(x > 0, dtype=np.int)
使用matpoltlib 繪制出階躍函數(shù)的圖形
import numpy as np
import matplotlib.pylab as plt
def step_function(x):
return np.array(x > 0, dtype=np.int)
x = np.arange(-5.0, 5.0, 0.1) # 生成從 -5.0 到 5.0 的矩陣, 步長(zhǎng)為0.1
y = step_function(x)
print(y)
plt.plot(x, y)
plt.ylim(-0.1, 1.1) # 指定y軸的范圍
plt.show()
np.arange(-5.0, 5.0, 0.1)在?5.0到5.0的范圍內(nèi)涯呻,以0.1為單位,生成NumPy數(shù)組([-5.0, -4.9, ... , 4.9])腻要。step_function()以該NumPy數(shù)組為參數(shù)复罐,對(duì)數(shù)組的各個(gè)元素執(zhí)行階躍函數(shù)運(yùn)算,并以數(shù)組形式返回運(yùn)算結(jié)果雄家。
對(duì)數(shù)組x效诅、y進(jìn)行繪圖,結(jié)果如圖所示趟济。
3.2.2 sigmoid 函數(shù)
sigmoid 函數(shù) 是神經(jīng)網(wǎng)絡(luò)經(jīng)常使用的一種函數(shù).
其中exp(-x)表示e^(?x)的意思.神經(jīng)網(wǎng)絡(luò)中用sigmoid函數(shù)作為激活函數(shù)進(jìn)行信號(hào)的轉(zhuǎn)換乱投,轉(zhuǎn)換后的信號(hào)被傳送給下一個(gè)神經(jīng)元。實(shí)際上顷编,上一章介紹的感知機(jī)和接下來(lái)要介紹的神經(jīng)網(wǎng)絡(luò)的主要區(qū)別就在于這個(gè)激活函數(shù)戚炫。其他方面,比如神經(jīng)元的多層連接的構(gòu)造媳纬、信號(hào)的傳遞方法等嘹悼,基本上和感知機(jī)是一樣的叛甫。
代碼實(shí)現(xiàn)sigmoid 函數(shù):
import numpy as np
def sigmoid(x):
return 1 / (1 + np.exp(-x))
"""
實(shí)際上,如果在這個(gè)sigmoid函數(shù)中輸入一個(gè)NumPy數(shù)組杨伙,則結(jié)果如下所示。
x = np.array([-1.0, 1.0, 2.0])
sigmoid(x)
array([ 0.26894142, 0.73105858, 0.88079708])
"""
使用matpoltlib 畫出sigmoid 函數(shù)
import numpy as np
import matplotlib.pylab as plt
def sigmoid(x):
return 1 / (1 + np.exp(-x))
x = np.arange(-5.0, 5.0, 0.1) # 生成從 -5.0 到 5.0 的矩陣, 步長(zhǎng)為0.1
y = sigmoid(x)
print(y)
plt.plot(x, y)
plt.ylim(-0.1, 1.1) # 指定y軸的范圍
plt.show()
3.2.3 sigmoid 函數(shù)與階躍函數(shù)的對(duì)比
-
不同點(diǎn)
通過(guò)函數(shù)圖像對(duì)比,相對(duì)于階躍函數(shù)只能返回0或1萌腿,sigmoid函數(shù)可以返回0.731 ...限匣、0.880 ...等實(shí)數(shù)(這一點(diǎn)和剛才的平滑性有關(guān))。也就是說(shuō)毁菱,感知機(jī)中神經(jīng)元之間流動(dòng)的是0或1的二元信號(hào)米死,而神經(jīng)網(wǎng)絡(luò)中流動(dòng)的是連續(xù)的實(shí)數(shù)值信號(hào)。
相同點(diǎn)
階躍函數(shù)和sigmoid函數(shù)雖然在平滑性上有差異贮庞,但是如果從宏觀視角看函數(shù)圖像對(duì)圖峦筒,可以發(fā)現(xiàn)它們具有相似的形狀。實(shí)際上窗慎,兩者的結(jié)構(gòu)均是“輸入小時(shí)物喷,輸出接近0(為0);隨著輸入增大遮斥,輸出向1靠近(變成1)”峦失。也就是說(shuō),當(dāng)輸入信號(hào)為重要信息時(shí)术吗,階躍函數(shù)和sigmoid函數(shù)都會(huì)輸出較大的值尉辑;當(dāng)輸入信號(hào)為不重要的信息時(shí),兩者都輸出較小的值较屿。還有一個(gè)共同點(diǎn)是隧魄,不管輸入信號(hào)有多小,或者有多大隘蝎,輸出信號(hào)的值都在0到1之間购啄。
且二者均是非線性函數(shù),sigmoid函數(shù)是一條曲線,階躍函數(shù)是一條像階梯一樣的折線末贾,兩者都屬于非線性的函數(shù)闸溃。
神經(jīng)網(wǎng)絡(luò)的激活函數(shù)必須使用非線性函數(shù)。換句話說(shuō)拱撵,激活函數(shù)不能使
用線性函數(shù)辉川。為什么不能使用線性函數(shù)呢?因?yàn)槭褂镁€性函數(shù)的話拴测,加深神經(jīng)網(wǎng)絡(luò)的層數(shù)就沒(méi)有意義了乓旗。線性函數(shù)只代表倍數(shù)的變化, 是一條直線, 比如 h(x)= 2*x ,那么即使是三層也是2*2*2*x,可以優(yōu)化為一層 8*x, 所以神經(jīng)網(wǎng)絡(luò)一定要使用非線性的函數(shù).
3.2.4 ReLU函數(shù)
最近使用的比較多的是ReLU函數(shù), ReLU(Rectified Linear Unit)函數(shù)在輸入大于0時(shí),直接輸出該值集索;在輸入小于等于0時(shí)屿愚,輸出0.
使用代碼構(gòu)造:
import numpy as np
def relu(x):
return np.maximum(0, x)
對(duì)應(yīng)的函數(shù)圖像:
3.3 多維數(shù)組的實(shí)現(xiàn)
- 如果掌握了NumPy多維數(shù)組的運(yùn)算汇跨,就可以高效地實(shí)現(xiàn)神經(jīng)網(wǎng)絡(luò)。下面介紹一些numpy中相關(guān)的API.
import numpy as np
A = np.array([[1, 2], [3, 4]])
print(A)
print(np.ndim(A)) # 輸出維度
print(A.shape) # 數(shù)組的形狀可以通過(guò)實(shí)例變量shape獲得,這里為 二行二列
B = np.array([[5, 6], [7, 8]])
C = np.dot(A,B) # A,B矩陣相乘
print(C)
"""
[[1 2]
[3 4]]
2
(2, 2)
[[19 22]
[43 50]]
"""
-
神經(jīng)網(wǎng)絡(luò)內(nèi)積
下面我們使用NumPy矩陣來(lái)實(shí)現(xiàn)神經(jīng)網(wǎng)絡(luò)妆距。這里我們以下圖中的簡(jiǎn)
單神經(jīng)網(wǎng)絡(luò)為對(duì)象穷遂。這個(gè)神經(jīng)網(wǎng)絡(luò)省略了偏置和激活函數(shù),只有權(quán)重娱据。
其中, X = (1,2).
import numpy as np
X = np.array([1, 2])
print (X.shape) # result: (2,)
W = np.array([[1, 3, 5], [2, 4, 6]])
print(W)
#[[1 3 5]
# [2 4 6]]
pirnt(W.shape) # result: (2, 3)
Y = np.dot(X, W)
print(Y) # result: [ 5 11 17]
如上所示蚪黑,使用np.dot(多維數(shù)組的點(diǎn)積),可以一次性計(jì)算出Y 的結(jié)果,能夠大大加快中剩。這意味著忌穿,即便Y 的元素個(gè)數(shù)為100或1000,也可以通過(guò)一次運(yùn)算就計(jì)算出結(jié)果结啼!如果不使用np.dot掠剑,就必須單獨(dú)計(jì)算Y 的每一個(gè)元素(或者說(shuō)必須使用for語(yǔ)句),非常麻煩郊愧。因此朴译,通過(guò)矩陣的乘積一次性完成計(jì)算的技巧,在實(shí)現(xiàn)的層面上可以說(shuō)是非常重要的.
總結(jié)
這部分學(xué)習(xí)了
- 神經(jīng)網(wǎng)絡(luò)與感知機(jī)的區(qū)別,
- 神經(jīng)網(wǎng)絡(luò)相關(guān)的函數(shù),
- 以及使用numpy復(fù)習(xí)了矩陣,簡(jiǎn)化運(yùn)算
下一部分學(xué)習(xí)具體神經(jīng)網(wǎng)絡(luò)的實(shí)現(xiàn).