前言:這只是我的一個學習筆記,里邊肯定有不少錯誤,還希望有大神能幫幫找找,由於是從小白的視角來看問題的,所以對於初學者或多或少會有點幫助吧。
1:人工全連接神經網絡和BP算法
<1>:人工神經網絡結構與人工神經網絡可以完美分割任意數據的原理:
本節圖片來源於斯坦福Andrew Ng老師coursea課件(此大神不多介紹,大家都懂)
在說明神經網絡之前,先介紹一下神經網絡的基礎計算單元,感知器。
上圖就是一個簡單的感知器,藍色是輸入的樣本,g(z)是激活函數,z=x1*w1+…,a=g(z)
這個東西可以用來干什么呢?我們可以令b=-30,w1=20,w2=20,此時限制輸入的x1和x2為0或者1,激活函數為sigmoid函數:
上圖為sigmoid函數圖像,可以看出當x很大時,此函數趨於1,當x很小時,此函數趨於0,寫出真值表,可以發現這個感知器完成了一個邏輯與的操作。
X1 | X2 | z | A |
0 | 0 | -30 | 0 |
0 | 1 | -10 | 0 |
1 | 0 | -10 | 0 |
1 | 1 | 10 | 1 |
將參數修改為b=-10,w1=20,w2=20,此時感知器又完成了一個邏輯或的操作,真值表就不寫了,也就是說改變這些圓圈圈之間的傳遞參數,可以使這個感知器完成邏輯或和邏輯與的操作。當然對一個輸入取非也不會有問題(b=10,w1=-20)。
因此,我們可以改變連接參數,從而使感知器完成與、或、非的操作。而將兩層感知器連接起來,不就可以完成或非、與非、異或等操作了唄。
舉一個例子,比如讓一個神經網絡分割下圖圓圈和×:
這里重新將邏輯或和邏輯與畫成類似上圖的格式:
而我們要達到的目標則為:
所以想要分割這兩組點,第一層求一次或得到一個神經元,再求一個與得到另一個神經元,第二層求與就能得到上圖結果了:
神經網絡就是這樣分割一個普通線性分類器很難分割的區域的
當神經元和神經網絡的層數更高的時候,區分下面的數據也就不是什么問題了:
<2>:神經網絡的結構和前向運算:
上圖是Andrew Ng老師課程中的截圖,這就是一個典型的神經網絡,我們設\( \theta ^{(j)} \)為j層到j+1層的傳遞矩陣,從輸入層(藍色)到中間的第二層,就有:
\( a_{1}^{(2)} = g(\theta_{10}^{(1)}x_{0}+\theta_{11}^{(1)}x_{1}+\theta_{12}^{(1)}x_{2}+\theta_{13}^{(1)}x_{3}) \)
\( a_{2}^{(2)} = g(\theta_{20}^{(1)}x_{0}+\theta_{21}^{(1)}x_{1}+\theta_{22}^{(1)}x_{2}+\theta_{23}^{(1)}x_{3}) \)
\( a_{3}^{(2)} = g(\theta_{30}^{(1)}x_{0}+\theta_{31}^{(1)}x_{1}+\theta_{32}^{(1)}x_{2}+\theta_{33}^{(1)}x_{3}) \)
同理,第二層到輸出層:
\( h_{\theta}(x)=a_{1}^{(3)}=g(\theta_{10}^{(2)}x_{0}+\theta_{11}^{(2)}x_{1}+\theta_{12}^{(2)}x_{2}+\theta_{13}^{(2)}x_{3}) \)
注意這個神經網絡的輸出只有一個值而神經網絡的輸出可以有任意個,這里僅以此為例不再展開寫,上邊就是當已知每一層之間的系數矩陣時,神經網絡求解的過程。
只要我們可以通過某種訓練手段的得到神經網絡各層之間的系數矩陣,那么神經網絡就可以用來完成機器學習任務了。
從這里開始,將通過一個例子來說明,感覺這樣子可以描述的更清楚些吧。可能也是應為我比較笨。。。
我們假設有m=500張樣本圖片,每個圖片的分辨率是3*3而且都是黑白的,圖片的label(標簽)有3類,分別是烤雞、烤鴨和烤全羊。我們構建一個雙隱層的神經網絡來判斷任意一個輸入的3*3圖片是什么東西。這個神經網絡只用來舉例,一個9像素的圖片當然什么實際的意義了。。。
這個神經網絡的結構就是下邊這個樣子了:
輸入層是9個像素點的灰度值組成的向量X,有m=500個樣本,所以dim(X)=500*9,中間兩個隱層我們假設它們各有14個節點, \(h_1\)一個隱層(hidden layer),\(dim(h_1)\)=500*14,\(h_2\)層是第二個隱層,\(dim(h_2)\)=500*14,output就是輸出層,有3個類別分別表示雞,鴨,羊。維度當然是500*3了,參數W的維度分別是9*14,9*14,b則是一個500*14,500*14的矩陣,但b的每一行都是一樣的,=>符號表示全連接,如果徹底畫出來是這個樣子的(懶得用visio畫了,沒啥意義)
對於bias項b,還可以這樣理解:在每一層中加一個節點,這個節點固定值為1,從這個節點映射到下一層的每一個節點的參數組成的向量就是參數b,對於500個樣本,就是每一個樣本行都加上這個bias項了。
在numpy中,這么操作:
z1 = X.dot(W1) + b1 #這里b1是1*14的 a1 = np.tanh(z1) #激活函數還有tanh、ReLU等等 z2 = a1.dot(W2) + b2 …
X*W1出來是500*14,在numpy中加b1(1*14)就是在X*W1的每一行都加b1,同理,如果加某個500*1的向量,是每一列都加這個向量。這么設計有點困惑呢。。。數學老師說矩陣加法維度不一致不讓加的。
計算假設函數的公式就是下邊這樣:
\( h_1=g(x*W_1+b_1) \)
\( h_2=g(h_1*W_2+b_2) \)
\( output=h_3=g(h_2*W_3+b_3) \)
這樣,對於這500個樣本,每個樣本的每一類的得分就都計算出來了。當然由於參數組是隨機搞到的,得分不一定合理,比如一個標簽是烤鴨的樣本,烤鴨的得分反而是最低的,這都有可能,想要定性的衡量這套參數的靠譜程度,從而優化這套參數,就要介紹下一個工具,損失函數了。
<3>:損失函數(cost function),判斷當前這套參數的性能:
損失函數是干啥的呢,在這個例子中我們有m個樣本,然后我們隨便搞一套參數組合,把這m個樣本分別扔到神經網絡中去運算出輸出,由於我們知道這些樣本的標簽,所以就可以判斷我們之前隨便搞的這套參數組合能不能用來求解未知的數據,比如有一枚數據的標簽是烤鴨,將這個數據扔到神經網絡里,算出來的得分是:
烤鴨:2分,燒雞:12分,烤全羊:-78分
很明顯嘛,這套參數得到的值不對,按照神經網絡的值不就把鴨子認成雞了嘛。損失函數就是衡量這個不對的程度的函數,顧名思義嘛,損失函數的值越小,說明你這套參數就越靠譜,越能表達樣本總體的特征。
在Andrew Ng課程中,老師直接給出了損失函數:
\( j(\theta)=-\frac{1}{m}[\sum\limits_{i=1}^m\sum\limits_{k=1}^Ky_k^{(i)}logh_{\theta}(x^{(i)})_{k}+(1-y_k^{(i)})log(1-h_{\theta}(x^{(i)})_{k})]+\frac{\lambda}{2m}\sum\limits_{l=1}^{L-1}\sum\limits_{i=1}^{S_l}\sum\limits_{j=1}^{S_{l+1}}(\theta_j^{(l)})^2 \)
K means the number of output units.
L means total number of layers in the network.
\(S_l\)means number of units in layer l(not counting bias unit).
m是樣本數量.
這個損失函數其實是一個logistic regression問題的交叉熵損失(cross entropy loss),一步一步來看這個損失是怎么來的哈,比較復雜。我舉的這個栗子是softmax回歸問題,就是多分類問題。
第一步是對輸出進行歸一化處理(normalize),我們可以將得分轉換成概率形式,假設某個標簽為烤鴨的樣本得分是:
烤鴨:2分,燒雞:12分,烤全羊:-78分
歸一化為:
烤鴨:\(\frac{e^2}{e^2+e^{128}+e^{-78}}\)
燒雞:\(\frac{e^{12}}{e^2+e^{128}+e^{-78}}\)
烤全羊:\(\frac{e^{-78}}{e^2+e^{128}+e^{-78}}\)
這樣,輸出的樣本得分就變成了:
烤鴨:4.5*10^-5,燒雞:幾乎是1,烤全羊:8.2*10-40
這樣子就可以很方便的和樣本標簽做比較了,比如這個樣本的標簽是烤鴨,標簽向量y就是[1,0,0]了。不是的話需要轉換成這種形式。
交叉熵損失,就是將這些概率和標簽中正確的概率向量的差加起來再求一個負對數,剛剛的數據比較龐大,我們假設計算得到的輸出概率向量為[0.1,0.5,0.4],這個意思就是神經網絡認為你輸入的這張圖片有0.1的概率是烤鴨,0.5的概率是燒雞…,但實際輸入的樣本圖片的標簽是烤鴨,也就是[1,0,0]。那么他在每一個類別上的損失就是[1-0.1,0.5-0,0.4-0]
而cross entropy loss就等於
\(-\frac{1}{m}[log(1-0.1)+log0.5+log0.4]\)
現在再感受一下這個式子。恍然大悟吧。如果這個類別標簽是0,說明你輸出的softmax概率全部是損失,如果這個類標簽是1,你輸出的概率本該是1,但差了1-p那么多,所以損失就是1-p。
\( j(\theta)=-\frac{1}{m}[\sum\limits_{i=1}^m\sum\limits_{k=1}^Ky_k^{(i)}logh_{\theta}(x^{(i)})_{k}+(1-y_k^{(i)})log(1-h_{\theta}(x^{(i)})_{k})] \)
K means the number of output units.
L means total number of layers in the network.
\(S_l\)means number of units in layer l(not counting bias unit).
恩我是應為笨才說的這么清楚的。。。
至於為毛叫交叉熵損失。。等我學完信息論再回答吧,留個坑。
有了損失函數的定義后,我們可以隨機初始化一組系數矩陣,然后使用梯度下降的方法找到一組(使用大量的樣本)令損失函數最小的系數矩陣,這就是SGD(隨機梯度下降)
<4>:BP與SGD:
在介紹SGD算法之前,先簡單說一下什么是梯度下降(gradient descent)。我們假設有一個凸函數如圖所示,如何從隨機的一點逐漸收斂到這個函數的最小值呢?
下邊的偽代碼就是梯度下降。當循環次數達到一定數量時,此時的x就非常接近f(x)的最小值了。
Repeat until convergence{
\(\delta=\alpha\frac{d}{dx}f(x)\)
x=x-\(\delta\)
}
a是一個更新率,當a很小時梯度收斂的很慢,當a較大時梯度收斂的較快,當a過大時可能無法收斂,比如x減去一個很小的負值,函數值比原來距離正確的最小值點更遠了。可見對於這樣一個平滑的凸函數,迭代的步子會隨着次數增加越邁越小,原因就是導數越來越小了。這樣就會使得x逐漸逼近最小值點。
對於神經網絡的cost function,它不僅僅有一個參數,我們便需要求出cost function對每個參數的偏導數,在最后統一進行參數更新后進行下一輪迭代。
神經網絡系統使用正向傳播求當前參數的損失,然后反向傳播回傳誤差,根據誤差信號迭代修正每層的權重。SGD算法(stochastic gradient descent)的第一步是隨機初始化每一個參數。Stochastic的意思正是隨機。通過這組隨機的參數計算得到每一個神經元的輸入輸出值和損失函數后,就可以求損失函數對各個參數的偏導數了,梯度更新的那個delta就等於alpha*偏導數。偏導數怎么求就不多說了,高中數學嘍。
而BP算法則是用來求那一堆偏導數的,BP的意思是反向傳播。就是把最后一層的誤差反向傳遞回別的神經元,得到每一層的誤差函數,從而解出偏導數。
我們定義\(\delta^{(l)}_j\)為第l層,節點j的誤差
對於輸出層(第四層)
\(\delta^{(4)}=a^{(4)}-y\),這里當然每一個都是3維的向量
往前傳遞:
\(\delta^{(3)}=((\Theta^{(3)})^T\delta^{(4)}).*g^{'}(z^{(3)})\)
\(\delta^{(2)}=((\Theta^{(2)})^T\delta^{(3)}).*g^{'}(z^{(2)})\)
則損失函數對於每個參數的偏導數為:
\(\dfrac{\partial J(\Theta)}{\partial \Theta_{i,j}^{(l)}} = \frac{1}{m}\sum_{t=1}^m a_j^{(t)(l)} {\delta}_i^{(t)(l+1)}\)
這個東西的證明出奇的復雜,有興趣的可以谷歌一下,當每一個偏導數都求出來后,就可以套用上邊的梯度下降算法迭代出來最佳的參數組合嘍。這就是神經網絡。
好了,上邊的例子就是一個圖像分類的問題demo,差不多說的很清楚了吧。然后考慮一下實際的圖像分類問題,會遇到哪些問題呢?
首先圖像的分辨率不能是9像素了,這能看出來啥啊,然后就是圖像的類別,也不能就3類了,這個新球上的圖片還是有個幾千個類別的吧,這樣就會遇到一些計算上的問題,比如圖片的分辨率是1080p,那么輸入維度就是1980*1200=2376000,通常隱層節點數量要大於輸入維度,而隱層層數也隨着分類問題的復雜而提高,就算一個圖像分類神經網絡的隱層節點數量和輸入維度一致,那傳遞參數W維度就成了。。。200w*200w=2萬億個了。。。這么大的數據量,老黃也沒轍,只能優化算法。
關於深度的神經網絡為何難以訓練有很多細節,可以推薦一本在線書:
http://neuralnetworksanddeeplearning.com/chap5.html
#我還沒看完。。
寫到這里深刻感覺到關於深度神經網絡的知識量還是很大的,這里只做知識結構梳理和重要的key point描述。其實對於此類知識,我個人的看法是掌握原理即可move on,需要其中的細節再去查看資料,對每一個細節都詳細證明是有一些浪費時間的,對於初學者(just like me)來說,很快的了解並將這個技術應用到一個測試平台上是更重要的,其次是緊跟潮流看看最新的進展是在研究什么。數學很重要,但它只是工具罷了。我們要掌握的是如何用數學解決問題。
具體怎么搞?
卷積神經網絡