MLP-2

kiands
11 min readFeb 18, 2022

--

1.1 前文回顧

前文說到:辨識MNIST資料集中的一個數字是把28*28的灰度圖像使用Keras的Flatten轉換為長度為784的array。這就是上圖中,Input下方784的意義。Hidden層是一個比較黑箱的部分,結構沒有具體的限制,但是不同的結構確實會影響到MLP的表現。

在上圖中,我們演示的是一個接近原汁原味的MLP:由輸入層、隱藏層、輸出層組成。在層和層之間,人工神經元的連接是全連接(無冗余、無缺失)。不過隱藏層在此有兩層,是為了畫圖的方便,同時也可以用16*16來體現一點複雜度(前文的隱藏層內部是1層,128個神經元)。明確了結構之後,我們就會開始稍微深入神經網路的細節。

1.2 輸入的內容

用一個小型的範例來舉例:假如我們有一張圖:

假設它每個畫素格子的灰階是0到255的範圍,並且在正規化(除以255)之後變為了灰色:0.25;黑色:0;白色:1。這個5*5的圖像中畫素格子所代表的數字展開後,就變成了[1,1,0.25,1,1,1,1,0,1,1,1,1,0,1,1,1,1,0,1,1,1,1,0.25,1,1]。推廣到MNIST中,28*28的灰度圖正規化展開後的array長度就是784,並且被類似的數字填充。每個數字都有對應的人工神經元接收它們並產生輸出。

1.3 輸入層和隱藏層的邂逅

上圖中,輸入層的神經元(紅框)只有一個輸入,但是對於隱藏層中藍框處的神經元而言,它的輸入就很複雜了:輸入層的784個神經元都會將他們處理後的結果輸出到藍框處。上一層的輸出會變成下一層的輸入(術語就是激活值)。我們設計神經網路結構,會決定上一層的激活值如何影響下一層的激活值。

1.4 權重(w)和偏置(b)

我們常說事有輕重緩急,當我們聽到很多建議的時候就會評估這些事情的重要性。權重就是這一抽象概念的具體表現之一。對於藍框中的神經元,784個輸入幾乎不可能一視同仁,所以每一個輸入在此時就會乘上一個權重,我們可以給權重賦予編號:比如從w1到w784。這個權重還會根據情況改變(在1.4中我們暫時不討論這個改變)。

我們也可以給第一層的激活值賦予編號:從a1到a784。至此,我們可以得到表達式1:

w1a1 + w2a2 + w3a3 + … + w784a784

這個公式的結果如果不加以限制,由於權重的數值範圍可以很廣泛,從正數到負數都有可能。所以計算出來的結果又可能超出我們期望的[0,1]。此時,我們又需要用一次激勵函數去將所有的結果的值域壓縮一下(上一次用其實是在輸入層的神經元內)。我們用sigmoid函數來壓縮值域。sigmoid函數也可以被換成別的函數。如此,表達式就變成了如下所述的表達式2:

σ(w1a1 + w2a2 + w3a3 + … + w784a784)

但有時候,我們可能會想要最後調整一下神經元,引入一些例外情況來影響神經元的輸出。操作的方法就是引入偏置,即在上述表達式後面加減一個實數,變成表達式3。

σ(w1a1 + w2a2 + w3a3 + … + w784a784) ± b

上圖中隱藏層左邊,右邊都是16個神經元。以藍框所在的左側為例,表達式3的狀況就會出現16次。那就有784*16個權重和16個偏置。整個神經網路就有:784*16 + 16*16 + 16*10個權重,16 + 16 + 10個偏置。一共是13002個。這也稱作「13002個參數」。如果我們看過一些老式的大型計算儀器,上面會有很多旋鈕。如果這個神經網路是那樣的機器,它就會有13002個旋鈕。我們改變旋鈕,儀器就會有很大的變化。我們說的神經網路的學習,其實就是讓電腦按照一定的規則去更改這些旋鈕(設定這13002個參數)。這些參數的計算因為其分佈結構上的規律,會用線性代數作為數學工具。而線性代數的矩陣運算恰好是GPU所擅長的,這就是GPU和神經網路以及一些加速器發揮作用的地方。

接下來,我們就要討論神經網路如何修改這些權重和偏置。

2.1 神經網路如何學習

人的學習需要範例和適當的反饋來調整認知。神經網路也用計算機能處理的方式接收合適的範例和反饋,來調整參數。當學習和訓練結束,人和神經網路都可以應對測驗。這個測驗就是範例中從未見過的同類型資料。訓練的成效在此時就顯示出來了。在我們設計的模式中,向機器推廣「學習」的概念就是一個優化的過程。這個優化一般是尋找函數的最小值(當然「優化」這個主題又是非常深奧的),運用在其中的數學工具是微積分。

1.4的表達式3的結果單獨拿出來,可以用「神經元之間連結強度的量化值」來形容。在創建神經網路的時候,我們需要初始化得出這些結果的參數。如果用隨機數,神經網路的表現就會非常令人迷惑(以MNIST來說,就是10個輸出神經元代表的機率「難捨難分」。好的輸出應該是有一個輸出神經元代表的機率非常高,其它的接近0)。在這裏,我們需要能夠讓計算機知道運算的結果不盡人意。如何做到這一點的話,解決方法之一就是設計一個函數,用函數的計算結果來傳達信息。這個函數會被稱作cost function。

MNIST這裡的cost function的計算就是:實際輸出的機率和期望的輸出機率一一作差,再把十個差的平方的和計算出來。這個和(cost)越接近0,結果越理想;和越大,結果越糟糕。我們要考慮的就是上萬個訓練用的樣本輸入神經網路之後的平均cost。這個cost同時也告訴我們前面的13002個參數的整體表現的好壞。但是知道了好壞,我們還需要知道如何改進。改進方法就是盡可能用一種方法找到我們複雜的cost funciton的最小值。

不過在這裏,微積分可能不太管用。因為這些cost function都會很複雜。所以有一個方法就是輸入任意數值,尋找函數變小的方向。此時如果知道了函數某點的斜率就更好辦了(單變數情況下)。斜率為正數,繼續向x軸左邊檢查;斜率為負數,可以往x軸右邊檢查。如果有合適的跨度或者部驟,就可以有很高的希望找到函數的局部最小值(全局最小值有時候可遇不可求)。

在多變數情況下函數的圖形就不是二維能描述了,斜率也就不適用。我們需要瞭解一個概念:函數的梯度會告訴我們函數數值最陡峭的上升方向。那反過來操作,用負的梯度就可以知道函數數值下降最快的方向。這個方法就名為梯度下降。這個梯度是一個向量,指明了在高維空間中的一個方向。

我們這次的cost function擁有13002個參數,負梯度就有13002維。將它的每個維度一一對應到參數上,我們的參數就可以得到改變。然我們就可以把cost降低的影響反饋到實際的神經網路中。把這些改變擴散到神經網路上的每一個參數上,和前面得到cost時的路徑是相反的,所以叫做反向傳播(倒傳遞)。

2.2 反向傳播(倒傳遞)

理論上,cost function的結果需要所有樣本輸入網路之後才能評估,那樣梯度下降和反向傳播也需要等待這個完整的過程。不過也有辦法可以用部分樣本來加速調整。

讓我們假設在訓練中,有一張手寫2的圖片輸入之後在輸出層的結果和期望的結果是這樣的:

此時我們就要思考在出現這個結果之後如何修改前面的13002個參數以及這個過程的細節。結果需要體現為:2的實際機率變大,其它的實際機率變小。全部模擬一遍無疑是複雜的,不過我們可以局部聚焦在兩層之間的連接、一個神經元上。就以這個負責輸出2的機率的神經元為例:

現在,有表達式σ(w1a1 + w2a2 + w3a3 + … + w16a16) + b = 0.2。要改變這個輸出,我們可以修改權重w、修改偏置b或者修改激活值a。這16條連接的權重大小各不相同。不過我們可以知道前一層中,不同神經元的激活值不同。改變擁有大激活值的神經元和輸出層中被選中的神經元的連接權重對於改變表達式的結果效力會比較明顯。或者說,改變已經比較大的權重的性價比比較高。但我們同樣需要注意:這16個權重會參與隱藏層和輸出層間所有的計算。所以這將是一個反覆拉鋸的過程。因為一旦我們針對某個輸出層神經元的表現改變了一些權重,然後這些被改變的權重降低了別的輸出層神經元的表現,這些權重將會再次被更動,直到「妥協」出一個「對大家來說都可以接受的結果」。

同時我們需要明確一個規範:我們更動權重會讓輸出層的機率發生變化。這些變化的幅度應該要對當前選中的神經元更有利:打一個比方,我們現在選中的是2,2現在的預測機率是0.2,8現在的預測機率是0.3。當我們改變權重後,2增加的機率應該要大於8減少的機率。因為2距離目標1很遠,但是8距離目標0相對比較近。

對於這連接負責2的機率的前一層16個神經元,經過運算我們就會得到這16個神經元上期待發生的變化。那麼這10個輸出層神經元都將會產生一組變化的期望值。這10組期望值(每組16個)相加之後,就成為指導權重變化的數值。

對於完整的神經網路,從靠後的層間連接到靠前的層,把上面這個過程一直推廣到最前面的層,把所有的變化全部算出來。

當然我們不要忘了,上面兩段只是描述了一個樣本中的變化。我們在其它樣本輸入網路後同樣需要經過一樣的操作。這樣,我們紀錄下每個樣本對「權重調整的建議」,取平均值,就成為了倒傳遞的核心。詳情可以參考下表進行想像。計算會在2.3中提及。

不嚴謹地說,這個13002維度的平均值組成的向量就是我們之前提到的cost function的梯度。

2.3 計算

2.3.1 簡化的運算

簡化情況下,我們用連成直線的四個神經元來演示計算,期望輸出y為1.0。C為Cell,L為Layer。d代表微積分的delta。

此時表格中C1L4的cost(此處用c來代表),cC1L4為(0.66–1)²;C1L4的激活值a由σ(wC1L4*aC1L3 + bC1L4)得出。為了書寫方便,我們把wC1L4*aC1L3 + bC1L4定義為xC1L4。這樣,我們可以發現wC1L4,aC1L3,bC1L4決定了xC1L4;xC1L4決定了aC1L4。y和aC1L4決定了cost。微調這些變數,結果c就會有變化。其中微調w會發生什麼,用chain rule來說,就是:dcC1L4/dwC1L4 = dxC1L4/dwC1L4 * daC1L4/dxC1L4 * dcC1L4/daC1L4。

cC1L4 = (aC1L4 — y)²
dcC1L4/dxC1L4 = 2(aC1L4 — y)
從上面這個表達式,我們可以看出導數的變化和網路最終的輸出和期望值之差成正比。
daC1L4/dxC1L4 = σ’(xC1L4)
C1L4的激活值對xC1L4求導就是求sigmoid函數的導數。
dxC1L4/dwC1L4 = aC1L3
整理一下:
dcC1L4/dwC1L4
= dxC1L4/dwC1L4 * daC1L4/dxC1L4 * dcC1L4/dxC1L4
= 2(aC1L4 — y) * σ’(xC1L4) * aC1L3

但這只是包含一個樣本的cost對wC1L4的導數。我們仍然需要記住:總cost是許許多多訓練樣本所有cost的總平均。這個總平均只是梯度向量的一個分量(梯度向量由cost function對每一個權重w和每一個偏置b求偏導得出)。完成了梯度的計算,我們就可以知道下一輪訓練中,我們的參數需要如何設定,知道神經網路的輸出層表現變得理想為止。

2.3.2 推廣

2.3.1的內容只是用一對一連接的神經元解釋了公式。在2.3.2中,我們會用上圖中的結構配合下標來解釋更完整的計算。由於數學公式的限制,大多數內容將用圖形來展示。

L1中的神經元編號是下標k;L2中的神經元編號是下標j。L1和L2中的權重的編號格式則是:wkjL2。C1L2的期望輸出是y0,C2L2的期望輸出是y1。y的下標同L2,使用j。

以上,就是神經網路中一些原理的推導和計算。

參考

1.3Blue1Brown的YouTube教學

2.吳恩達Andrew Ng的機器學習https://study.163.com/course/courseLearn.htm?courseId=1004570029

--

--