4、全连接神经网络
淺層神經網絡
- 1 對全連接神經網絡結構的理解
- 1.1 單個節點如何工作
- 1.2 整個網絡如何工作
- 2 激活函數
- 2.1 激活函數的對比與選擇
- 1)sigmoid 函數
- 2)tanh 函數
- 3)ReLU 函數
- 4)Leaky-ReLU 函數
- 5)線性激活函數與線性層
- 2.2 為什么要用非線性的激活函數
- 3 網絡參數初始化
- 3.1 隨機初始化
- 3.2 初始值的大小
- 4 神經網絡的梯度下降算法
- 4.1 梯度下降大概步驟
- 4.2 前向傳播與反向傳播的計算
- 4.3 各個矩陣或向量的尺寸
1 對全連接神經網絡結構的理解
1.1 單個節點如何工作
這里以包含一個隱藏層和一個輸出層的兩層全連接神經網絡為例(嚴格的說輸入層并不能算為一層),上圖左是它的結構圖。將網絡中的某個節點放大,得到了上圖右。與邏輯回歸采用 sigmoid 函數作為激活函數不同的是,適用于神經網絡的激活函數有很多,包括但不限于 sigmoid 函數,下面會詳解講解。除了激活函數的差別外,神經網絡中單個節點和邏輯回歸卻具有相同的結構,都是先執行一個線性運算,然后再通過激活函數做一個非線性的運算。
神經網絡往往包含很多層,一層中又包含多個節點,這里用上標[i]表示網絡中的第 i 層,用下標j表示第 j 個節點。數據集包含多個樣本,這里用上標(k)表示第 k 個樣本。圖中的 zzz 表示網絡節點在執行線性運算后的結果,aaa 表示網絡節點在執行激活函數(activation function)后的輸出。輸入層并不執行任何計算,所以它并不能算為一個層,只不過我們習慣上這樣叫它。輸入層也可以看作第 0 層,則輸入的向量 xxx 也可以看作是第 0 層的輸出,即 a[0]=xa^{[0]}=xa[0]=x。對于輸入的某個樣本的特征向量 xxx ,神經網絡的每個節點是如何工作的呢?這里以第 1 層為例,給出了第一層節點的計算過程,如下圖右。
1.2 整個網絡如何工作
通過上圖我們已經知道了單個節點是如何工作的。那么對于某個樣本的特征向量 xxx ,整個神經網絡的節點是如何合作并最終輸出 y^\hat{y}y^? 的呢?由圖中的箭頭可以知道,神經網絡從輸入層開始,上一層的輸出作為下一層的輸入,直到輸出最終的結果。我們把第 i 層的所有節點的參數向量 w 轉置后按順序放進矩陣 W[i]W^{[i]}W[i] 中,再把第 i 層的所有節點的參數 b 按順序組合成一個列向量 bbb,那么對于上圖第 1 層的運算過程,我們用 z[1]=W[1]x+bz^{[1]} = W^{[1]}x+bz[1]=W[1]x+b ,a[1]=sigmoid(z[1])a^{[1]}=sigmoid(z^{[1]})a[1]=sigmoid(z[1]) 這兩個式子便能完成上圖中相同的工作。只不過我們這里把每一層所有節點的 w,b,aaa,z 分別放在了一起。通過這種向量化的方式,現在我們能更方便地計算每一層節點的輸出了。對于輸入的某個樣本的特征向量 xxx,我們按照同樣的方式計算整個神經網絡的輸出,如下圖所示。
對于包含 m 個樣本的樣本集,其特征矩陣 X={x(1),x(2)?,x(m)}.X = \{x(1),x(2) ? , x(m)\} .X={x(1),x(2)?,x(m)}. 上面是以單個樣本 xxx 為單位進行運算,如果要以這種方式完成對整個樣本集的預測的話,必須通過大量的 for 循環,下圖左給出了通過循環對所有樣本進行預測的做法。但是對于龐大的數據集和稍微復雜的網絡結構來說,用 for 循環這無疑會花費大量的計算時間。為了使我們的網絡模型更加高效,一般使用向量化的計算方式代替 for 循環,下圖右展示了通過向量化計算對所有樣本進行預測的做法。
2 激活函數
2.1 激活函數的對比與選擇
神經網絡往往包含多個層,不同層的激活函數可以不一樣。下面是幾種常見的激活函數。
1)sigmoid 函數
表達式:sigmoid(z)=11+e?zsigmoid(z) = \frac{1}{1 + e^{-z}}sigmoid(z)=1+e?z1?
函數圖像:
sigmoid 函數的值域為 (0,1)。從圖中可以看出,當因變量 zzz 取值為 0 時,sigmoid 曲線的斜率(梯度)最大,計算出來為 0.25。當因變量 zzz 的取值越大或越小時,sidmoid 曲線的斜率(梯度)就越小。當 zzz > 5 或 zzz < -5 時,sigmoid 曲線的斜率(梯度)幾乎為零。如此一來,當我們在通過梯度下降算法來更新參數的時候,如果 zzz 的取值過大,那么參數更新的速度就會變得非常緩慢。
所以在神經網絡中選擇 sigmoid 函數作為激活函數并不是一個很好的選擇,但有個例外就是二元分類的輸出層。因為二元分類的標簽 yyy 要么是 0,要么是 1,所以我們希望輸出的 y^\hat{y}y^? 能表示當前樣本屬于某類別的概率,而概率又介于 0 和 1 之間,這恰好和 sigmoid 函數的值域相符。所以在做二元分類的時候,輸出層的激活函數可以選擇 sigmoid。
2)tanh 函數
表達式:tanh(z)=ez?e?zez+e?ztanh(z) = \frac{e^z-e^{-z}}{e^z+e^{-z}}tanh(z)=ez+e?zez?e?z?
函數圖像:
如果選擇 tanh 作為隱藏層的激活函數,效果幾乎總是比 sigmoid 函數要好,因為 tanh 函數的輸出介于 -1 與 1 之間,激活函數的平均值就更接近于 0,而不是 0.5,這讓下一層的學習更加方便一點。
和 sigmoid 函數類似,當因變量 zzz 取值為 0 時,tanh 曲線的斜率(梯度)最大,計算出來為 1。當因變量 zzz 的取值越大或越小時,sigmoid 曲線的斜率(梯度)就越小。所以 tanh 也會面臨和 sigmiod 函數同樣的問題:當 zzz 很大或很小時,tanh 曲線的斜率(梯度)幾乎為零,這對于執行梯度下降算法十分不利。
3)ReLU 函數
表達式:ReLU(z)=max(0,z)ReLU(z) = max(0,z)ReLU(z)=max(0,z)
函數圖像:
目前在機器學習中最受歡迎的激活函數是 ReLU (Rectified Linear Unit),即修正線性單元。現在 ReLU 已經成為了隱層激活函數的默認選擇。如果不確定隱層應該使用哪個激活函數,可以先嘗試一下 ReLU。
當 zzz > 0 時,曲線斜率為 1;當 zzz < 0 時,曲線的斜率為 0;當 zzz = 0 時,曲線不可導,斜率就失去了意義,但在實際編程的時候可以令其為 1 或 0,盡管在數學上這樣不正確,但不必擔心,因為出現 zzz = 0 的概率非常非常小。ReLu函數的好處在于對于大部分的 zzz,激活函數的斜率(導數)和 0 差很遠。所以在隱層中使用 ReLU 激活函數,神經網絡的學習速度通常會快很多。ReLU 也有一個缺點,那就是當 zzz 為負數時,ReLU 曲線的斜率為 0,不過這在實踐中不會有什么問題,因為有足夠多的隱層節點使 zzz 大于 0。
4)Leaky-ReLU 函數
表達式:ReLU(z)=max(kz,z),k通常為0.01ReLU(z) = max(kz,z) \ \ \ ,k通常為0.01ReLU(z)=max(kz,z)???,k通常為0.01
函數圖像:
通過前面對 ReLU 的介紹我們知道了 ReLU 函數的缺點:當 zzz 為負數時,ReLU 曲線的導數為 0。而 Leaky-ReLU 則是另一個版本的 ReLU,當當 zzz 為負數時,Leaky-ReLU 曲線的導數不再為 0,而是有一個平緩的斜率。這通常比 ReLU 要好,不過實際中使用的頻率卻不怎么高。
5)線性激活函數與線性層
到現在為止,我們討論的都是非線性的激活函數。那么什么時候我們可以使用線性激活函數或者線性的層呢?通常其用處不是很多,當想要處理一些關于壓縮的特殊問題時,可以在隱藏層中使用,或者處理回歸問題在輸出層中使用。除此之外,基本上沒有其他地方能用到線性激活函數或者線性的層了。
2.2 為什么要用非線性的激活函數
先來看一看正常情況下,使用非線性激活函數 g(z)g(z)g(z) 的神經網絡完成正向傳播的計算表達式:
現在,我們去掉激活函數 g[1](z[1])g^{[1]}(z^{[1]})g[1](z[1]) 和 g[2](z[2])g^{[2]}(z^{[2]})g[2](z[2]),網絡中的兩個層就變成了線性層。正向傳播的表達式就變成了
z[1]=W[1]x+b[1]z^{[1]}=W^{[1]}x+b^{[1]}z[1]=W[1]x+b[1] z[2]=W[2]z[1]+b[2]z^{[2]}=W^{[2]}z^{[1]}+b^{[2]}z[2]=W[2]z[1]+b[2]
再把兩個式子合并為一個
z[2]=W[2](W[1]x+b[1])+b[2]=(W[2]W[1])x+(W[2]b[1]+b[2])z^{[2]} = W^{[2]}(W^{[1]}x+b^{[1]})+b^{[2]} = (W^{[2]}W^{[1]})x+(W^{[2]}b^{[1]}+b^{[2]})z[2]=W[2](W[1]x+b[1])+b[2]=(W[2]W[1])x+(W[2]b[1]+b[2])
令
W′=W[2]W[1]W'=W^{[2]}W^{[1]}W′=W[2]W[1] b′=W[2]b[1]+b[2]b'=W^{[2]}b^{[1]}+b^{[2]}b′=W[2]b[1]+b[2]
則
z[2]=W′x+b′z^{[2]} = W'x+b'z[2]=W′x+b′
通過上面的推倒可以看到,對于輸入神經網絡的線性組合 xxx,在去掉激活函數后,先經過第一個隱層的計算,然后神經網絡在輸出層最終輸出的 z[2]z^{[2]}z[2] 還是一個線性組合。這樣的話還不如把輸出層的參數設置為 W′W'W′ 和 b′b'b′,然后直接去掉隱層。也就是說,無論有多少個線性隱層,最終的輸出還是一個線性組合,還不如不要隱層,因為多個線性函數的組合還是一個線性函數。那么要是所有隱層都去掉非線性激活函數,而在輸出層保留一個 sigmoid 函數呢?它的效果和沒有任何隱層的邏輯回歸是一樣的。
3 網絡參數初始化
3.1 隨機初始化
在邏輯回歸的問題中,把權重參數初始化為零是可行的。但把神經網絡的權重參數全部初始化為零,并使用梯度下降算法將無法獲得預期的效果。
以上面這個簡單的神經網絡為例。其與隱藏層關聯的權重矩陣 W[1]W^{[1]}W[1] 是一個 2 x 2 的矩陣?,F在將這個矩陣的初始值都設為 0,同樣我們將偏置矩陣 b[1]b^{[1]}b[1] 的值也都初始化為 0。 b[1]b^{[1]}b[1] 的初始值全為 0 不會影響最終結果,但是將權重參數矩陣 W[1]W^{[1]}W[1] 初始值都設為 0 會引起下面的問題。
無論輸入什么樣的特征向量 xxx,當進行前向傳播的計算時,a1[1]a_1^{[1]}a1[1]? 與 a2[1]a_2^{[1]}a2[1]? 是相等的,所以他們隱層的兩個節點對輸出層唯一節點的影響也是相同的。當進行反向傳播的計算時,也會導致代價函數對 W1[1]W_1^{[1]}W1[1]? 與 W2[1]W_2^{[1]}W2[1]? 的偏導不會有差別。所以在更新參數后, W1[1]W_1^{[1]}W1[1]? 與 W2[1]W_2^{[1]}W2[1]? 還是相等的。這又導致在進入下一次迭代后,依然是重蹈覆轍。
在上面這個例子中,隱藏層中上面的節點和下面的節點是相同的,它們實現的是完全相同的功能。在機器學習中,這種情形被稱為是“對稱”的。當把神經網絡的權重參數全部初始化為 0 后,無論運行梯度下降多長時間,所有的隱藏神經元都將依然是“對稱”的。這種情況下,再多的隱層節點也是無用的,因為它們依然提供的是完全相同的功能,這并不能給我們帶來任何幫助。 所以我們希望兩個不同的隱藏單元能實現不同的功能 ,而進行隨機初始化能夠解決這個問題。
3.2 初始值的大小
利用python編寫神經網絡時,通常使用 W[i] =np.random.randn((rows,cols))*0.01 這樣的方式來對所有的權重矩陣 W 進行隨機初始化并乘上一個非常小的數,比如 0.01。這樣操作后,就將權重參數矩陣賦予了非常小的隨機初始值。對于 b 來說,b并不會由于初始值為零而產生對稱問題,所以使用 b[i]=np.zeros((rows,1)) 這樣的方式來對所有的偏置矩陣 b 初始化為零。
現在權重參數矩陣 W 已經完成了隨機初始化,不同的隱藏單元會承擔不同的計算工作,我們也不會再遇到類似前面說的對稱問題了。那么為什么會在初始化 W 的時候使用 0.01 這個常量? 為什么是 0.01 而不把它設置為 100 或 1000?當在網絡中用到了 tanh 或sigmoid 激活函數時,如果 W 很大,那么 Z=WTx+bZ=W^Tx+bZ=WTx+b(的絕對值)也相應的會非常大,而此時 A=sigmoid(Z)A=sigmoid(Z)A=sigmoid(Z) 或 A=tanh(Z)A= tanh(Z)A=tanh(Z) 圖像對應的部分的斜率就非常小,這意味著梯度下降會非常緩慢,所以整個學習過程也會變得尤為緩慢。而如果在神經網絡中未使用任何sigmoid或者tanh激活函數,這種情況可能不明顯。
有時候會有比 0.01 更為合適的數值,當訓練一個僅含一個隱藏層的神經網絡時,顯而易見 0.01 這個數值在類似于這樣不含過多隱藏層的淺層神經網絡中是非常合適的。但當你要訓練一個非常非常復雜的深度神經網絡時,可以通過嘗試使用不同的數值并觀察梯度下降的結果來確定最適合的數值。
4 神經網絡的梯度下降算法
4.1 梯度下降大概步驟
神經網絡同樣可以使用梯度下降算法來更新網絡的參數 W 和 b。具體來說就是通過多次迭代,一步一步通過更新神經網絡每一層節點的參數來減小神經網絡輸出的誤差,最終誤差達到最小時的參數就是我們要尋找的參數。大概步驟為:
在循環中完成:
????1、前向傳播:從第一層到輸出層,逐層計算網絡輸出;
????2、計算代價函數;
????3、反向傳播:從輸出層到第一層,逐層計算各層的梯度 ?J?W\frac{\partial{J}}{\partial{W}}?W?J? 與 ?J?b\frac{\partial{J}}{\partial}?b?J? ;
????4、更新參數:W=W??J?WW=W-\frac{\partial{J}}{\partial{W}}W=W??W?J? , b=b??J?bb=b-\frac{\partial{J}}{\partial}b=b??b?J? .
4.2 前向傳播與反向傳播的計算
假設這里有一個 LLL 層的神經網絡,不同的層激活函數可以不一樣,我們用g[i](Z[i])g^{[i]}(Z^{[i]})g[i](Z[i])表示第 i 層的激活函數。則在前向傳播中,前一層的輸出作為后一層的輸入,一層一層的計算直至輸出 A[L]A^{[L]}A[L],如下圖所示。
假設我們現在還是做一個二分類任務,則輸出層的選擇 sigmoid 激活函數,即 g[L](z[L])=sigmiod(z[L])g^{[L]}(z^{[L]}) = sigmiod(z^{[L]})g[L](z[L])=sigmiod(z[L])。然后代價函數我們定義為:
J=?1m∑i=1m(y[L](i)log?a[L](i)+(1?y[L](i))log?(1?a[L](i)))J = -\frac{1}{m}\sum_{i=1}^{m}(y^{[L](i)}\log{a^{[L](i)}}+(1-y^{[L](i)})\log{(1-a^{[L](i)})})J=?m1?i=1∑m?(y[L](i)loga[L](i)+(1?y[L](i))log(1?a[L](i)))
則在后向傳播中,我們通過鏈式求導法則從后向前一層一層的計算代價函數對 WWW 與 bbb 的偏導 ?J?W\frac{\partial{J}}{\partial{W}}?W?J? 與 ?J?b\frac{\partial{J}}{\partial}?b?J?。下圖展示了反向傳播的計算過程。(注意:為了書寫方便,下圖用符號 ddd 表示對代價函數 JJJ 某個變量的偏導。比如 dzdzdz 表示 ?J?z\frac{\partial{J}}{\partial{z}}?z?J?)。
4.3 各個矩陣或向量的尺寸
需要注意的是,向量化計算對參與運算的矩陣或向量的尺寸十分敏感。在運算時,我們需要對各個矩陣或向量的尺寸有十分清楚的了解。假如: xxx 是一個包含 n 個特征值的列向量,且樣本集包含 m 個樣本,網絡的第 i 層有 n[i]n^{[i]}n[i] 個節點,則各個矩陣或向量的尺寸為:
| YYY | 1?m1*m1?m |
| W[i]W^{[i]}W[i] | n[i]?n[i?1]n^{[i]}*n^{[i-1]}n[i]?n[i?1] |
| b[i]b^{[i]}b[i] | n[i]?1n^{[i]}*1n[i]?1 |
| Z[i]Z^{[i]}Z[i] | n[i]?mn^{[i]}*mn[i]?m |
| A[i]A^{[i]}A[i] | n[i]?mn^{[i]}*mn[i]?m |
另外在反向傳播中,代價函數對某個矩陣的偏導得到的梯度矩陣與這個矩陣的尺寸是一致的,即:
dW[i]dW^{[i]}dW[i] 與 W[i]W^{[i]}W[i] 的尺寸一致;
db[i]db^{[i]}db[i] 與 b[i]b^{[i]}b[i] 的尺寸一致;
dZ[i]dZ^{[i]}dZ[i] 與 Z[i]Z^{[i]}Z[i] 的尺寸一致;
dA[i]dA^{[i]}dA[i] 與 A[i]A^{[i]}A[i] 的尺寸一致。
總結
- 上一篇: 只会用 xxl-job?更强大的新一代分
- 下一篇: unity怪物攻击玩家减血_Unity-