Neural Networks

項目地址:https://github.com/Daya-Jin/DL_for_learner
原博客:https://daya-jin.github.io/2018/12/13/NeuralNetworks/

神經網絡

模型結構

上圖是一個簡單的神經網絡,xix_{i}爲樣本特徵,y^\hat{y}爲網絡輸出,個變量之間的關係滿足:

a[1]=σ(i=13θi[0]xi+b[0])y^=g(i=14θi[1]a[1]+b[1]) \begin{aligned} a^{[1]}&=\sigma(\sum\limits_{i=1}^{3}\theta^{[0]}_{i}x_{i}+b^{[0]}) \\ \hat{y}&=g(\sum\limits_{i=1}^{4}\theta^{[1]}_{i}a^{[1]}+b^{[1]}) \\ \end{aligned}

其中σ(x)\sigma(x)稱爲激活函數(activation function),g(x)g(x)爲輸出激活函數;輸入數據XX所在的位置稱爲輸出層(input layer),aija_{i}^{j}所在的位置稱爲隱藏層(hidden layer),輸出預測結果的稱爲輸出層(output layer),圖中每一個圓圈稱爲神經元(Neuron)。

最常見的激活函數爲σ(x)=11+ex\sigma(x)=\frac{1}{1+e^{-x}},即logistics regression中的sigmoid函數;而輸出激活函數需要根據模型任務來定,迴歸任務下爲g(x)=xg(x)=x,二分類任務下g(x)=11+exg(x)=\frac{1}{1+e^{-x}},多分類任務下g(x)=softmax()g(x)=softmax(這裏待補充);損失函數也由具體任務來定。

數學原理

保持與代碼實現上的一致性,令

a[1]=σ(xθ[0]+b[0]) a^{[1]}=\sigma(x\theta^{[0]}+b^{[0]})

xx的形狀爲(1,3)(1,3)a[0]a^{[0]}的形狀爲(1,4)(1,4),那麼有矩陣乘法的性質得θ[0]\theta^{[0]}的形狀爲(3,4)(3,4)

y^=σ(a[1]θ[1]+b[1]) \hat{y}=\sigma(a^{[1]}\theta^{[1]}+b^{[1]})

y^\hat{y}的形狀爲(1,1)(1,1),所以θ[1]\theta^{[1]}的形狀爲(4,1)(4,1)。由矩陣乘法性質不難推出,若當前層的單元數爲n[i]n^{[i]},下層單元數爲n[i+1]n^{[i+1]},則當前層權重矩陣的形狀爲:

dim(θ[i])=(n[i],n[i+1]) dim(\theta^{[i]})=(n^{[i]},n^{[i+1]})

整個網絡的輸出可以寫成:

z[1]=a[0]θ[0]+b[0]a[1]=σ(z[1])z[2]=a[1]θ[1]+b[1]a[2]=σ(z[2]) \begin{aligned} z^{[1]}&=a^{[0]}\theta^{[0]}+b^{[0]} \\ a^{[1]}&=\sigma(z^{[1]}) \\ z^{[2]}&=a^{[1]}\theta^{[1]}+b^{[1]} \\ a^{[2]}&=\sigma(z^{[2]}) \\ \end{aligned}

以二分類爲例,簡單寫下神經網絡的反向傳播過程。爲便於後面的計算,先明確σ(x)=11+ex\sigma(x)=\frac{1}{1+e^{-x}}的導數:

σ(x)x=1(1+ex)2(ex)=11+exex+111+ex=11+ex(111+ex)=σ(x)(1σ(x)) \begin{aligned} \frac{\partial{\sigma(x)}}{\partial{x}}&=\frac{-1}{(1+e^{-x})^{2}}\cdot(-e^{-x}) \\ &=\frac{1}{1+e^{-x}}\cdot\frac{e^{-x}+1-1}{1+e^{-x}} \\ &=\frac{1}{1+e^{-x}}\cdot(1-\frac{1}{1+e^{-x}}) \\ &=\sigma(x)\cdot(1-\sigma(x)) \\ \end{aligned}

首先,損失函數爲:

L=ylna[2](1y)ln(1a[2]) L=-y{\ln}a^{[2]}-(1-y){\ln}(1-a^{[2]})

逐層對變量求導:

Δa[2]=La[2]=ya[2]+1y1a[2]Δz[2]=Δa[2]a[2]z[2]=Δa[2]a[2](1a[2])=a[2]yΔθ[1]=Δz[2]z[2]θ[1]=Δz[2]a[1]Δb[1]=Δz[2]z[2]b[1]=Δz[2] \begin{aligned} {\Delta}a^{[2]}&=\frac{\partial{L}}{\partial{a^{[2]}}} \\ &=-\frac{y}{a^{[2]}}+\frac{1-y}{1-a^{[2]}} \\ {\Delta}z^{[2]}&={\Delta}a^{[2]}\cdot\frac{\partial{a^{[2]}}}{\partial{z^{[2]}}} \\ &={\Delta}a^{[2]}{\cdot}a^{[2]}(1-a^{[2]}) \\ &=a^{[2]}-y \\ {\Delta}\theta^{[1]}&={\Delta}z^{[2]}\cdot\frac{\partial{z^{[2]}}}{\partial\theta^{[1]}} \\ &={\Delta}z^{[2]}{\cdot}a^{[1]} \\ {\Delta}b^{[1]}&={\Delta}z^{[2]}\cdot\frac{\partial{z^{[2]}}}{\partial{b^{[1]}}} \\ &={\Delta}z^{[2]} \\ \end{aligned}

更前一層的梯度爲:

Δa[1]=Δz[2]z[2]a[1]=Δz[2]θ[1]Δz[1]=Δa[1]a[1]z[1]=Δz[2]θ[1]a[1](1a[1])Δθ[0]=Δz[1]z[1]θ[0]=Δz[1]a[0]Δb[0]=Δz[1]z[1]b[0]=Δz[1] \begin{aligned} {\Delta}a^{[1]}&={\Delta}z^{[2]}\cdot\frac{\partial{z^{[2]}}}{\partial{a^{[1]}}} \\ &={\Delta}z^{[2]}\cdot\theta^{[1]} \\ {\Delta}z^{[1]}&={\Delta}a^{[1]}\cdot\frac{\partial{a^{[1]}}}{\partial{z^{[1]}}} \\ &={\Delta}z^{[2]}\cdot\theta^{[1]}{\cdot}a^{[1]}(1-a^{[1]}) \\ {\Delta}\theta^{[0]}&={\Delta}z^{[1]}\cdot\frac{\partial{z^{[1]}}}{\partial\theta^{[0]}} \\ &={\Delta}z^{[1]}{\cdot}a^{[0]} \\ {\Delta}b^{[0]}&={\Delta}z^{[1]}\cdot\frac{\partial{z^{[1]}}}{\partial{b^{[0]}}} \\ &={\Delta}z^{[1]} \end{aligned}

這是使用sigmoid函數爲激活函數下二分類神經網絡的梯度。其實如果在更深層的神經網絡中推導的話,假設有hh層隱藏層,那麼除了最後一層隱藏層,前h1h-1層的梯度都可以寫成遞推表達式,因爲最後一層隱藏層的梯度是由損失函數推出來的,而前h1h-1層的梯度都是由當前層的輸出aa推出來的。遞推式展開可以寫成累乘,那麼累乘就會有一個問題:當神經網絡層數過深並且每一層的梯度都小於1時,那麼越前面層的梯度就會越小,若都大於1,則越前面層的梯度就會越大。這就是深層神經網絡中梯度消失梯度爆炸的問題。

原博客的Python實現指導

tensorflow實現指導

Activation Function

sigmoid

DNN初期默認採取的激活函數是sigmoid函數:

σ(x)=11+exp(x) \sigma(x)=\frac{1}{1+exp(-x)}

該函數圖像爲:

可以看到該函數在±5\pm{5}處就幾乎達到閾值了,相對應的是一個梯度飽和問題。每一層激活函數的輸入是z[i]=a[i1]θ[i1]+b[i1]z^{[i]}=a^{[i-1]}\theta^{[i-1]}+b^{[i-1]},如果這個值稍微大一點(超出±5\pm{5}),那麼就會導致該層激活函數的梯度變得及其微小,影響反向傳播算法的執行。

另外,sigmoid函數的輸出範圍是(0,1)(0,1),這會帶來另一個隱含問題。每一層的輸出都是正的,那麼該層對於優化參數的局部梯度爲:a[i+1]w[i]=a[i+1](1a[i+1])a[i]\frac{\partial{a^{[i+1]}}}{\partial{w^{[i]}}}=a^{[i+1]}(1-a^{[i+1]})a^{[i]},該值恆爲正。在梯度下降法的優化過程中,該特性會導致參數在一次迭代中要麼都往正方向更新,要麼都往負方向更新,相當於每次更新參數都沿軸向更新。

sigmoid函數的第三個缺點就是其中的指數函數需要一定的計算量。

tanh

DNN激活函數的另一個選擇:

tanh(x)=exexex+ex tanh(x)=\frac{e^{x}-e^{-x}}{e^{x}+e^{-x}}

其圖像爲:

可以看到tanh函數把輸入映射到了(1,1)(-1,1)區間,雖然對梯度下降法的收斂有一定加速作用,但是對於sigmoid函數存在的另外兩個問題,tanh函數同樣存在,甚至比sigmoid函數更嚴重。

Rectified Linear Unit

整流線性單元(ReLU)激活函數的表達式爲:

f(x)=max(0,x) f(x)=max(0,x)

其有如下優點:

  • 在正域上不存在函數上限,也不會存在梯度飽和的問題
  • 計算簡單
  • 收斂速度快於sigmoid激活函數
  • 更符合生物神經學

不過因爲ReLU的左半邊恆爲0,右邊恆爲正,同樣存在一個隱含的問題。ReLU函數在計算梯度時對負值是不響應的,負域的梯度恆爲00,如果在反向傳播時傳過來一個負的梯度值,那麼該神經元再往前傳播時的梯度貢獻始終是00,相當於該神經元已“壞死”。在某些情況下,如果在模型的整個訓練過程中,經過該神經元的梯度始終是負的,那麼該神經元在整個訓練過程持續性“壞死”,甚至還會影響到前面層的神經元,產生連鎖反應,導致前面的神經元更容易“壞死”或“持續性壞死”。

Leaky ReLU

帶泄露的ReLU是爲了解決ReLU“壞死”問題而出現的,其表達式爲:

f(x)=max(0.01x,x) f(x)=max(0.01x,x)

其圖像跟ReLU的區別在於負域,Leaky ReLU的負域不恆爲零,而是一個稍微傾斜的直線,這樣就避免了神經元“壞死”的問題。同時Leaky ReLU還有一個變種,當把負域直線的斜率參數化後,就得到了Parametric ReLU:

f(x)=max(αx,x) f(x)=max({\alpha}x,x)

其中α\alpha(0,1)(0,1)區間的任何值。Leaky ReLU與PReLU的缺點顯而易見:引入了額外的超參數,並且在實踐上不見得比ReLU好。

ELU

待補充,其優點沒太看懂

Weight Initialization

Constant Initialization

如果把所有的權重參數都初始化爲同樣的常數,那麼同一層的所有的神經元只等效爲一個神經元。

Small random numbers

對於小型網絡,常見的初始化方法爲初始化一個服從N(0,0.01)\mathcal N(0,0.01)的隨機分佈。但是該策略對大型網絡而言並不是一個好選擇,考慮前向傳播過程,由前往後每一層的輸出會越來越小,直至爲00,在反向傳播過程中同樣會造成梯度消失的問題。

類似地,如果權重初始化的太大,對於某些激活函數如sigmoid與tanh而言,會導致每一層激活後的輸出都在飽和區域,該層對參數的梯度非常小,然後造成梯度消失。

Xavier Initialization

看出權重參數初始化得太大或太小都不好,對於有飽和區的激活函數而言,需要儘量避免激活輸出進入飽和區。在講Xavier之前,先回顧一下方差的一些性質,對於獨立同分布的變量而言,有

D(X+Y)=D(X)+D(Y)D(XY)=D(X)D(Y)+D(X)E(Y)2+D(Y)E(X)2 \begin{aligned} D(X+Y)&=D(X)+D(Y) \\ D(XY)&=D(X)D(Y)+D(X)E(Y)^{2}+D(Y)E(X)^{2} \\ \end{aligned}

若各變量都是零均值,上式可以寫爲:

D(X+Y)=D(X)+D(Y)D(XY)=D(X)D(Y) \begin{aligned} D(X+Y)&=D(X)+D(Y) \\ D(XY)&=D(X)D(Y) \\ \end{aligned}

現假設權重參數θ\theta與輸入數據xx都爲零均值,方差vv的獨立同分布變量,那麼在忽略偏置項時某一層的線性輸出爲:

z[1]=xθ[0]=nIxjθj[0] z^{[1]}=x\theta^{[0]}=\sum\limits_{n_{I}}x_{j}\theta_{j}^{[0]}

其中nIn_{I}表示上一層的神經元數。那麼可以得到,當前層線性輸出值的均值爲00,方差爲:vz[1]=nI×vx×vθ[0]v_{z^{[1]}}=n_{I}{\times}v_{x}{\times}v_{\theta^{[0]}}。我們希望的是每一層的輸入與輸出儘量同分布,那麼令vz[1]=vxv_{z^{[1]}}=v_{x},得:vθ[0]=1/nIv_{\theta^{[0]}}=1/n_{I}。上面只考慮了正向傳播,那麼在反向傳播時,同樣希望每一層的參數梯度也同分布,那麼有:vθ[0]=1/nOv_{\theta^{[0]}}=1/n_{O},其中nOn_{O}爲當前層的神經元數。

Xavier Initialization的推薦做法是將權重參數初始化爲一個均值爲00,方差爲2nI+nI\frac{2}{n_{I}+n_{I}}

Batch Normalization

在權重參數初始化一節中講到,如果希望神經網絡學到東西,那麼在正向傳播時激活輸出不能進入飽和區,即不能讓反向傳播過程中參數梯度過小,令每一層的輸出與輸入服從同分布即可解決該問題。Batch Normalization的思想就是預設一個分佈函數,並對每一層的線性輸出做操作,使其強行服從該分佈。

以標準正態分佈爲例,BN在對每一層的線性輸出都做一次Normalization,使得每層的激活函數總是接受一個服從標準正態分佈的輸入值:

z[i]=a[i1]θ[i1]z^[i]=z[i]E(z[i])D(z[i]) \begin{aligned} z^{[i]}&=a^{[i-1]}\theta^{[i-1]} \\ \hat{z}^{[i]}&=\frac{z^{[i]}-E(z^{[i]})}{\sqrt{D(z^{[i]})}} \\ \end{aligned}

經上述轉化過後的線性輸出服從標準正態分佈。當然標準正態分佈的線性輸出只是預設的一種特殊情況,爲了增強靈活性,BN在上述過程後還有一步線性變換的操作:

z^[i]=γz^[i]+β \hat{z}^{[i]}=\gamma\hat{z}^{[i]}+\beta

最後這一部相當於把標準正態分佈推廣到了任意參數的正態分佈,其中γ\gammaβ\beta可以通過學習得到。不難發現,若γ=D(z[i])\gamma=\sqrt{D(z^{[i]})}β=E(z[i])\beta=E(z^{[i]}),則z^[i]=z[i]\hat{z}^{[i]}=z^{[i]}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章