使用矩陣運算驅動神經網路資料加工鏈

對於學過線性代數的人來說,矩陣運算絕對算得上是一場噩夢。特別是做矩陣乘法時,兩個大方塊,每個方塊裡面有好多數字,你需要把一個方塊中一行裡的所有數字跟另一個方塊裡面的所有數字做乘法,然後再求和,頭昏腦漲的算了半天才得到新矩陣的一個數值,忙活了半天,耗費了大量精力後,你發現居然算錯了,只能再來一遍,那時候我想你恨不得一把火把代數課本付之一炬。

上一節,我們手動計算了一個只有兩層,每層只有兩個節點的神經網路,那時候的手動計算已經讓我們精疲力盡了,試想一下任何能在現實中發揮實用效果的神經網路,例如用於人臉識別的網路,往往都是幾百幾千層,每層至少幾百幾千個節點,這種大規模網路,你要想想上一節一樣用筆和紙去算,那可是不可想象的。

為了處理這種不可想象的繁重之極的計算任務,惡習的矩陣就能派上用場。矩陣在兩方面能簡化神經網路的資料運算,一方面各種運算壓縮在一種簡單的數學格式中,使用同一的矩陣運演算法則就能流水線般的自動化執行各種運算,這種特性特別適合用計算機去實現,其二是很多程式語言對矩陣運算有非常好的支援,我們當下使用的Python就是,它對矩陣運算的支援就猶如對簡單的數字進行加減乘除一樣方便。因此依靠矩陣,我們就能找到一種簡單有效而又快速的方式完成神經網路龐雜的資料運算。

矩陣其實就是我們前面提到過的二維張量,它的運算在前面章節詳細說過,這裡我們再次回顧一下。在神經網路的運算中,我們最常使用的就是矩陣乘法,如下圖:

使用矩陣運算驅動神經網路資料加工鏈

兩個矩陣相乘需要滿足的條件是,左邊矩陣的列數必須等於右邊矩陣的行數,相乘時,把左邊矩陣第i行所有元素,分別與右邊矩陣第j列裡每個元素做乘法,然後再依次相加,所得結果就是新矩陣第i行第j列的元素。

回到上一節神經網路的例子,我們看看矩陣運算如何運用。

使用矩陣運算驅動神經網路資料加工鏈

網路中第一層的兩個節點分別把訊號傳送給第二層的兩個節點,訊號傳送時需要經過權重的乘機運算,上圖中總共有四個權重,我們可以把四個權重組成一個兩行兩列的矩陣,第一層又接收兩個輸入訊號,這兩個訊號可以形成一個兩行一列的矩陣,於是第二層兩個節點所接收到的訊號值可以透過下面的矩陣運算獲得:

使用矩陣運算驅動神經網路資料加工鏈

第一層第一個節點接收到訊號值1。0後,根據權重,把訊號分解成兩部分,第一部分是1。0 * 0。9 = 0。9 傳遞給第二層節點1,第一層第二個節點接收訊號值0。5,根據權重,把0。5 * 0。3 = 0。15 傳遞給第二層節點1,於是第二層節點1接收到的訊號總量就是:

1。0 * 0。9 + 0。5 * 0。3 = 1。05

根據圖示,input_1 = 1。0, W(1,1) = 0。9, input_2 = 0。5, W(2,1) = 0。3, 轉換一下,第二層第一個節點所接收到的訊號值就是:

input_1 * W(1,1) + input_2 * W(2,1)

這個結果正好與前面矩陣運算等候右邊矩陣的第一行第一列一致,同理第二層第二個節點接收到的訊號量等於右邊矩陣的第二行第二列對應的值。如此一來,透過一次矩陣乘法運算,我們就可以得到第二層節點接收的訊號量了。由此,依靠矩陣,我們就能從數學上簡明的去描述訊號的傳遞和處理過程,我們用符號 X 表示當前一層神經元節點要接收的訊號量,用 W 對應上一層節點相對於當層節點的權重,用 I 表示上一層神經元接收的訊號量,於是便有:

X = W * I

注意,我們這裡用到的符號都是大寫,這樣用於區別符號對應的是矩陣,也就是一維或二維張量而不是簡單的一個數字。上面的矩陣乘法也成為點乘,python 對矩陣點乘及相關運算提供了很好的支援,這就是為何python被廣泛的應用與人工智慧應用的開發,我們把前面的運算轉換為如下程式碼:

import numpy as npW = np。array([ [0。9, 0。3], [0。2, 0。8] ])I = np。array([1。0, 0。5])X = W。dot(I)print(X)

上面程式碼執行後結果為:

使用矩陣運算驅動神經網路資料加工鏈

由於python對矩陣運算的良好支援,使得程式碼的編寫很簡單省事。著意味著不管一個神經網路有多少層,每層有多少個節點,其對應的也就是矩陣的大小而已,用python實現,只要用幾個for迴圈把相應矩陣裡面的數值填上,矩陣的點乘及相關運算全部交給編譯器來幫我們完成,我們可以把精力全部集中在演算法和邏輯的設計之上。

依靠矩陣運算,我們可以得到每層神經元節點所要接收的訊號量,也就是上面式子中的X,接著我們將X中每個值輸入啟用函式,就能得到該層神經元輸出給下一層的訊號量:

O = sigmoid (X)

注意到上面等式中的O是大寫,也就是它是一個向量而不是單個數值。根據當前掌握的理論,我看看如何計算一個三層,每層含有三個神經元的網路。該網路的結構圖如下:

使用矩陣運算驅動神經網路資料加工鏈

這裡我們順便引入幾個術語,第一層我們稱之為輸入層,最後一層,我們稱之為輸出層。中間一層,我們誠摯為隱藏層。根據前面的講解,我們不難理解,向量I的值為:[0。9, 0。1, 0。8],也就是:

使用矩陣運算驅動神經網路資料加工鏈

第一層神經元的職責很簡單,它就是接收輸入訊號,然後把信後分解後傳遞到下一層。隱藏層的神經元就要麻煩一點,他需要把上一層傳過來的訊號整合起來,要注意隱藏層每個神經元與輸入層的每個神經元都有連線,所以隱藏層的神經元所獲得的訊號量都分別來自輸入層的三個神經元。我們把輸入層神經元傳遞給隱藏層神經元間對應的權重轉換成矩陣如下:

使用矩陣運算驅動神經網路資料加工鏈

我們透過矩陣的列來解讀其中的含義,第一列的值為[0。9, 0。2, 0。1]它表示輸入層第一個神經元將輸入訊號的0。9傳給第二層第一個神經元,把輸入訊號的0。2傳給第二層第二個神經元,把輸入訊號的0。1傳給第二層第三個神經元。第二列和第三列數值的含義依次類推。在前面的結構圖中並沒有顯示第一層第一個神經元與第二層第三個神經元之間的訊號傳遞權重,但從上面矩陣可以看出,這個權重的值就是0。1。我們注意到,上面矩陣符號W右下角有”input_hidden”標註,它表示輸入層與隱藏層神經元間的訊號傳遞權重矩陣,對應的我們可以得到隱藏層和輸出層神經元間訊號傳遞權重矩陣如下:

使用矩陣運算驅動神經網路資料加工鏈

根據前面描述的公式: X = W * I,我們可根據矩陣運算得到隱藏層每個神經元應當接收的訊號量:

使用矩陣運算驅動神經網路資料加工鏈

根據上面計算,我們得知,隱藏層第一個神經元將接收的訊號量為1。16,第二個神經元將接收的訊號量為0。42,第三個神經元將接收的訊號量為0。62。我們在後續章節中將詳細講解如何使用Python編寫相關計算程式碼。第二層的輸入訊號量確定後,我們就可以使用啟用函式,計算第二層輸出給第三層的訊號量:

使用矩陣運算驅動神經網路資料加工鏈

回憶一下,啟用函式是 sigmoid(x) = 1 / (1 + exp(-x));我們把X中的每個值分別代入啟用函式,例如把1。16代入啟用函式,得到的輸出結果為 sigmoid(1。16) = 0。761,以此類推最後算的隱藏層輸出訊號量為:

使用矩陣運算驅動神經網路資料加工鏈

隱藏層神經元傳出訊號量後,輸出層的神經元會接收過來並進行相應計算後再輸出。同理隱藏層每個神經元都會把一部分訊號量傳遞給輸出層的每個神經元,隱藏層和輸出層的互動過程跟輸入層與隱藏層的互動過程完全是一模一樣的。於是我們完全可以依據前面的做法,再次運算輸出層神經元接收到的訊號量,假設隱藏層和輸出層神經元間的權重矩陣如下:

使用矩陣運算驅動神經網路資料加工鏈

於是對應的計算過程如下:

使用矩陣運算驅動神經網路資料加工鏈

也就是說,輸出層神經元接收到的訊號量為0。975,0。888,1。254。對應的結構圖如下:

使用矩陣運算驅動神經網路資料加工鏈

我們再次對輸出層神經元接收到的訊號量進行啟用函式的運算,得到結果如下:

使用矩陣運算驅動神經網路資料加工鏈

經過一系列的訊號傳遞和計算,在輸出層得到了最終結果:

使用矩陣運算驅動神經網路資料加工鏈

得到最終結果後,我們接下來該做什麼呢?透過前幾節我們得知,我們要把計算結果與給定的正確結果比較,得出偏差,根據偏差去調整模型的引數,以便讓下次計算你的結果與給定正確結果間的偏差越來越小,進而改進模型對資料進行預測的精確度,在下一節我們將詳細解讀,對於神經網路而言,如何透過輸出結果計算偏差,並反過來改進神經網路中的權重引數,從而提升神經網路對資料的計算精確度。

更多影片教程和內容請點選連結:

http://study。163。com/provider-search?keyword=Coding%E8%BF%AA%E6%96%AF%E5%B0%BC)

或在網易雲課堂中查詢關鍵字:用神經網路構造影象和語言識別系統