本系列文章都是關于UFLDL Tutorial的學習筆記
對1個有監督的學習問題,訓練樣本輸入情勢為(x(i),y(i))。使用神經網絡我們可以找到1個復雜的非線性的假定h(x(i))可以擬合我們的數據y(i)。我們先視察1個神經元的機制:
每一個神經元是1個計算單元,輸入為x1,x2,x3,輸出為:
其中f()是激活函數,經常使用的激活函數是S函數:
S函數的形狀以下,它有1個很好的性質就是導數很方便求:f’(z) = f(z)(1 ? f(z)):
還有1個常見的激活函數是雙曲正切函數tanh:
它的導數f’(z) = 1 ? (f(z))^2):
softmax激活函數的導數:f’(z)=f(z)?f(z)^2
神經網絡就是將上面的單個神經元連接成1個復雜的網絡:
如圖所示的3層神經網絡包括1個輸入層(3個輸入單元),1個隱藏層(3個計算單元),1個輸出層(1個輸出單元)。我們的所有參數描寫為(W,b) = (W(1),b(1),W(2),b(2))。Ws_ij表示的是第s層的第j個神經元到第s+1層的第i個神經元的權值,同理bs_i表示第s+1層的第i個神經元的偏差??芍?,偏差b的數目等于總的神經元的個數減去輸入層的神經元個數(輸入層不需要偏差),而權值w的數目等于神經網絡的連接數。最后的輸出計算以下:
更緊湊的寫法就是講其寫成向量的積,這樣以矩陣的情勢存儲系數可以加速計算。其中z表示該層所有神經元的輸入,a表示該層的輸出:
我們把上面這類求終究輸出的算法稱為向前傳播(feedforward)算法。對輸入層,我們可以用a1=x表示。給定l層的激活值al,計算l+1層的激活值的公式以下:
假定我們現在有1個固定大小為m的訓練集{(x1,y1),(x2,y2)…(xm,ym)},我們使用批梯度降落法來訓練我們的網絡。對每一個訓練樣本(x,y),我們計算它的損失函數以下:
引入規范化(權重衰減項:weight decay),使得系數盡量的小,總的損失函數以下:
需要注意的是通常規范化不會使用在偏差b上,由于對b使用規范化終究取得網絡和之前沒有太大區分。這里的規范化實際上是貝葉斯規范化的1個變體,具體可以看CS229 (Machine Learning) at Stanford的視頻。
上面的損失函數通常在分類和回歸問題中被用到。在分類中通常y取值為0,1,而我們的S函數的取值范圍是在[0,1]之間。而如果使用tanh函數,由于取值范圍是[⑴,1],我們可以將⑴表示0,1表示1,可以將0作為分界值。對回歸問題我們則需要先將我們的輸出按比例縮小到[0,1]之間,然后最后預測時相應的放大。
我們的目標是最小化損失函數J:首先隨機初始化w和b,由于梯度降落法容易局部最優,因此要進行屢次實驗,每次隨機選擇的參數不能相同。計算完所有樣本的損失后,更新w和b的公式以下,其中α是學習率:
對這個更新公式,最核心的是計算偏導。我們采取反向傳播( backpropagation)算法來計算偏導。反向傳播能夠幫助解釋網絡的權重和偏置的改變是如何改變代價函數的。歸根結柢,它的意思是指計算偏導數?C/?wl_jk和?C/?bl_j。但是為了計算這些偏導數,我們首先介紹1個中間量,δl_j,我們管它叫做第l層的第j個神經元的毛病量(error)。我們可以先計算1個樣本產生的梯度向量,最后求所有樣本梯度的平均便可:
反向傳播具體推導以下:
首先使用向前傳播計算出L2,L3…和輸出層的激活值。
對輸出層的每個輸出單元計算毛病量(a=f(z)利用偏導的鏈式法則):
對中間的隱藏層,我們計算每一個神經元的毛病量。其中括號里面可以理解為l+1層所有與l層該神經元相連的偏導乘以權值即為該神經元的損失值:
定義偏導以下:
根據neural networks and deep learning這本書中對反向傳播是這么理解的:
對第l層第j個神經元,如果zl_j變成zl_j+Δzl_j,那末會對終究整體的損失帶來(?C/?zl_j)*Δzl_j的改變。反向傳播的目的是找到這個Δzl_j,使得終究的損失函數更小。假定?C/?zl_j的值很大(不論正負),我們期望找到1個和?C/?zl_j符號相反的Δzl_j使得損失下降。假定?C/?zl_j的值趨近于0,那末Δzl_j對損失的改變是微不足道的,表示這個神經元和訓練接近最優了。這里以1個啟發式的感覺將?C/?zl_j看成度量1個神經元的誤差的方法。
受上面的啟發,我們可以定義第l層第j個神經元的誤差是:
輸出層誤差的方程,這個是根據偏導數鏈式法則 ?C/?z= (?C/?a)*(?a/?z) :
![]()
右式第1項表示代價隨著第j個神經元的輸出值的變化而變化的速度。假設C不太依賴1個特定的神經元j,那末δl_j就會很小,這也是我們想要的效果。右式第2項刻畫了在zl_j處激活函數σ變化的速度。如果使用2次代價函數,那末?C/?al_j = (aj ? yj)很容易計算。使用下1層的誤差δl+1來表示當前層的誤差δl,由于輸出層是可以肯定的計算出來,因此計算其它層要倒著向前傳播:
其中 (wl+1)T是第l+1層權重矩陣 wl+1的轉置。假定我們知道第l+1層的誤差δl+1,當我們利用轉置的權重矩陣(wl+1)T,我們可以憑直覺地把它看做是在沿著網絡反向移動誤差,給了我們度量在第l層輸出的誤差方法,我們進行Hadamard(向量對應位置相乘)乘積運算 ⊙σ′(zl)。這會讓誤差通過 l 層的激活函數反向傳遞回來并給出在第 l 層的帶權輸入的誤差 δ向量。
代價函數關于網絡中任意偏置的改變率:
誤差 δl_j 和偏導數值?C/?bl_j 完全1致,針對同1個神經元。
代價函數關于任何1個權重的改變率:
![]()
這告知我們如何計算偏導數?C/?wl_jk,其中 δl 和 al?1 這些量我們都已知道如何計算了。將其向量化:
其中 ain是輸入給權重 w 的神經元的激活值, δout 是輸出自權重 w 的神經元的誤差。當激活值 ain 很小, ain ≈ 0,梯度?C/?w 也會趨向很小。這樣,我們就說權重緩慢學習,表示在梯度降落的時候,這個權重不會改變太多。換言之, 來自低激活值神經元的權重學習會非常緩慢。
當 σ(zl_j) 近似為 0 或 1 的時候 σ 函數變得非常平。這時候σ’(zl_j) ≈ 0。所以如果輸出神經元處于或低激活值( ≈ 0)或高激活值( ≈1)時,終究層的權重學習緩慢。這樣的情形,我們常常稱輸出神經元已飽和了,并且,權重學習也會終止(或學習非常緩慢)。如果輸入神經元激活值很低,或輸出神經元已飽和了(太高或太低的激活值),權重會學習緩慢。
- 對l層的第j個神經元的權值做1點修改,會致使1些列激活值的變化:
- ?wl_jk 致使了在第l層 第j個神經元的激活值的變化 ?al_j。
- ?al_j 的變化將會致使下1層所有激活值的變化,我們聚焦到其中1個激活值上看 看影響的情況,無妨設 al+1_q :
![]()
- 這個變化 ?al+1_q 又會去下1層的激活值。實際上,我們可以想象出1條從 wl_jk到 C 的路徑,然后每一個激活值的變化會致使下1層的激活值的變化,終究是輸出層的代價的變化。假定激活值的序列以下 al_j, al+1_q, …,
aL⑴_n, aL_m,那末結果的表達式就是:
![]()
- 我們用這個公式計算 C 關于網絡中1個權重的變化率。這個公式告知我們的是:兩個神經元之間的連接實際上是關聯于1個變化率因子,這個因子是1個神經元的激活值相對其他神經元的激活值的偏導數。從第1個權重到第1個神經元的變化率因子是 ?al_j/?wl_jk。路徑的變化率因子其實就是這條路徑上的眾多因子的乘積。而全部的變化率 ?C/?wjk l就是對所有可能的從初始權重到終究輸出的代價函數的路徑的變化率因子的和。針對某1個路徑,這個進程解釋以下:
假定我們想最小化J(θ),我們可以進行梯度降落:
假定我們找到1個函數g(θ)等于這個導數,那末我們如何確認這個g(θ)是不是正確呢?回想導數的定義:
現在斟酌θ是個向量而不是1個值,我們定義:
其中θi+和θ幾近相同,除第i個位置上增加ε。
我們可以對每一個i 檢查下式是不是成立,進而驗證gi(θ)的正確性:
再利用反向傳播求解神經網絡時,正確的算法會得到下面這樣的導數,我們需要使用上面的方法來驗證得到的導數是都正確: