Lecture4,5,6:Neural Networks

Lecture4,5,6是把神經(jīng)網(wǎng)絡(luò)的一些東西分開講了,個(gè)人在筆記的順序上沒有按照原文來,我內(nèi)容重新編排后整理融合成了這一篇文章

Lecture4,5,6:Neural Networks

1. 神經(jīng)網(wǎng)絡(luò)抽象

1.1 抽象生物神經(jīng)元

? ? 我們?cè)诟咧芯蛯W(xué)過神經(jīng)元是什么樣的了。就是他前面有突觸,突觸可以傳遞遞質(zhì),興奮性遞質(zhì)到達(dá)的時(shí)候,神經(jīng)元電位上升,抑制性遞質(zhì)到達(dá),電位下降。總的來說就是接受前面的很多輸入,經(jīng)過一定處理后輸出。這是不是跟之前的 Linear Classification一樣?也就是說,我們可以將人腦單個(gè)神經(jīng)元的操作視為一個(gè)線性分類器。記住,不同突觸的能力不一樣,有的很厲害,一個(gè)突觸就可以影響整個(gè)神經(jīng)元的電位,因此,我們還需要一個(gè)權(quán)重。還有一點(diǎn),我們知道神經(jīng)元還有一個(gè)“興奮”的過程,在電位達(dá)到一定程度的時(shí)候神經(jīng)元會(huì)達(dá)到興奮狀態(tài),向后發(fā)送脈沖,沒達(dá)到時(shí)是不會(huì)發(fā)送脈沖的,為了模擬這一點(diǎn),我們?cè)O(shè)定一個(gè)“激活函數(shù)”??偟膩碚f,一個(gè)神經(jīng)元的運(yùn)行可以理解為,執(zhí)行操作
output = activation(W\cdot input)

1.2 人工神經(jīng)網(wǎng)絡(luò)(Artificial Neural Network)

? ? 什么叫做神經(jīng)網(wǎng)絡(luò)?很多個(gè)神經(jīng)元在一起連接成網(wǎng)就叫神經(jīng)網(wǎng)絡(luò)【滑稽.jpg】。最簡(jiǎn)單的神經(jīng)網(wǎng)絡(luò)可以看成是這樣的。



我們將不同神經(jīng)元之間分層,這樣做有方便計(jì)算的考慮。在后面的反向傳播中我們會(huì)提到這一點(diǎn)。

2. 神經(jīng)網(wǎng)絡(luò)基本計(jì)算

2.1 前向傳播 Forward Propogation

? ? 其實(shí)很容易發(fā)現(xiàn),神經(jīng)網(wǎng)絡(luò)的前向計(jì)算方式跟線性分類器其實(shí)是一樣的,實(shí)際上,線性分類器可以看作是一個(gè)只有輸入和輸出的神經(jīng)網(wǎng)絡(luò)。
不過由于激活函數(shù)的存在對(duì)每一層需要進(jìn)行兩次運(yùn)算即:
a = W\cdot x_{input} + b
x_{output} = activation(a)

2.2 反向傳播 Backward Propogation

? ? 如果我沒記錯(cuò)的話,在前面一片文章里,我就提到了一句求導(dǎo)好像就沒有下文了,這里比較詳細(xì)的說說。我們?nèi)匀恍枰?jiǎn)化問題……畢竟……太復(fù)雜算得太麻煩,而如果平時(shí)只使用框架也不需要頻繁進(jìn)行BP推導(dǎo)。

? ? 我們先從最簡(jiǎn)單的開始。我們假設(shè)我們的網(wǎng)絡(luò)輸出只有一個(gè)數(shù)字。也就是說,網(wǎng)絡(luò)是下面這樣的,其中W是一個(gè)n維行向量,b是一個(gè)數(shù)字,x是一個(gè)n維列向量,y是正確預(yù)測(cè)結(jié)果。我們先看下這是種什么情況。
向前傳播是x \to z = W\cdot x + b \to a = \sigma(z),\hat{y} = a\to L=(\hat{y} - y)^2
那么我們從最右邊開始倒推我們首先計(jì)算\frac{dL}{d\hat{y}} = 2\hat{y} - 2y
接著是\frac{d\hat{y}}{dz} = \hat{y}(1 - \hat{y})
其中z展開之后是z = w_1x_1 + w_2x_2 + …… + b
因此有\frac{dz}{dw} = x , \frac{dz}{db} = 1
最后相乘就得到了參數(shù)更新所需的梯度。到現(xiàn)在為止還是簡(jiǎn)單的鏈?zhǔn)椒▌t。

? ? 這個(gè)還比較簡(jiǎn)單,我們下面看看當(dāng)輸出有很多個(gè)的時(shí)候的反向傳播。我們先前進(jìn)一小步,把上面的W改成一個(gè)m\times n的矩陣,這樣b就是一個(gè)列向量了,x是輸入還不變,還是n維列向量,當(dāng)然相對(duì)應(yīng)的y,也變成向量了,m維。
向前傳播還是x \to z = W\cdot x + b \to a = \sigma(z),\hat{y} = a\to L=(\hat{y} - y)^2
現(xiàn)在我們開始從右面倒推,下面的表達(dá)式不是嚴(yán)格的數(shù)學(xué)表達(dá)式,理解意思即可
首先還是d\hat{y} =da = 2\hat{y} - 2y注意,這個(gè)式子里面的都是向量
接著是{dz} = d\hat{y} (\hat{y}(1 - \hat{y}))這個(gè)向量相乘,是逐元素相乘
db =dz
我們觀察發(fā)現(xiàn)z_i = \sum_j W_{i,j} x_j于是有 dW_{i,j} = dz_ix_j因此dW = dz\times x^T
現(xiàn)在我們已經(jīng)完成了多輸入多輸出的反向推導(dǎo)。這不就是神經(jīng)網(wǎng)絡(luò)中的一層嗎?我們接下來給出更通用的形式。

2.3 神經(jīng)網(wǎng)絡(luò)中一層的計(jì)算

2.3.1 參數(shù)

? ? 我們用l表示現(xiàn)在的層數(shù),a^{l - 1}表示這一層從上一層接受的輸入向量,W表示這一層的權(quán)重,b表示這一層加入的線性偏置,z為這一層的中間變量,a^l表示這一層的輸出值。

2.3.2 Forward Propogation(整個(gè)網(wǎng)絡(luò)的前向傳播也稱“推理”inference)

Input:a^{l - 1},Output:a^{l},Cache:z^l

z^l = W\times a^{l - 1}
a^l = avtivation(z^l)

2.3.3 Backward Propogation

Input:da^{l + 1},Output:da^{l},Cache:dW^l,db^l

dz^l = da^{l + 1} * activation'(z^{l})
dW^l = dz^l\times a^{l - 1}
db^l = dz^l
da^{l} = (W^l)^T \times z^l
注意:

  • 這里寫的是activation'(z^{l})但是上面舉的例子里面是{dz} = d\hat{y} (\hat{y}(1 - \hat{y})),這里的\hat{y}(1 - \hat{y})就是求導(dǎo)結(jié)果,不是寫錯(cuò)了(真寫錯(cuò)了記得留個(gè)言)。
  • 關(guān)于da^{l}的推導(dǎo),和上面dW的推導(dǎo)一樣,寫出式子,整理就行了。

2.3.4 trian

? ? 接下來根據(jù)我們獲得的dW,db來更新參數(shù)就可以了,更新方式并不止一種,在本文3.5節(jié)有介紹。

2.4 激活函數(shù) Activation Function

? ? 激活函數(shù)在之前不太好提,就是因?yàn)榉聪騻鞑フf的不很詳細(xì),不好講激活函數(shù)的優(yōu)缺點(diǎn),下面是幾種激活函數(shù)的介紹。

2.4.1 Sigmoid函數(shù)

\sigma (x) = \frac{1}{1 + e^{-x}}

  • 我們看到,這個(gè)函數(shù)兩側(cè),太平了,所以如果處理不當(dāng),會(huì)導(dǎo)致“梯度消失”的問題。我們看出這個(gè)函數(shù)輸出是[0,1]的,于是,我們可以想象,其實(shí)一層層下去,這個(gè)函數(shù)會(huì)慢慢右移,最后,就會(huì)無法學(xué)習(xí),初始化權(quán)重比較大也會(huì)導(dǎo)致同樣的問題。
  • 同樣是因?yàn)楹瘮?shù)輸出是[0,1]的。如果輸入神經(jīng)元的數(shù)據(jù)總是正數(shù),那么梯度在反向傳播的過程中,將會(huì)要么全部是正數(shù),要么全部是負(fù)數(shù)(具體依整個(gè)表達(dá)式而定)。這將會(huì)導(dǎo)致梯度下降權(quán)重更新時(shí)出現(xiàn)z字型的下降。

2.4.2 Tanh函數(shù)

tanh(x) = 2\sigma(2x) - 1
和sigmoid一樣,它也存在飽和問題,但是和sigmoid不同的是,它的輸出是零中心的。因此,在實(shí)際操作中,tanh比sigmoid更受歡迎。注意,tanh是一個(gè)簡(jiǎn)單放大的sigmoid.

2.4.3 ReLU函數(shù)

ReLU(x) = max(0,x)
線性整流函數(shù)(Rectified Linear Unit, ReLU),又稱修正線性單元

  • 優(yōu)點(diǎn):相較于sigmoid和tanh函數(shù),ReLU對(duì)于隨機(jī)梯度下降的收斂有巨大的加速作用( Krizhevsky 的論文指出有6倍之多)。這是由它的線性,非飽和的公式導(dǎo)致的。
  • 優(yōu)點(diǎn):sigmoid和tanh含有指數(shù)運(yùn)算等耗費(fèi)計(jì)算資源的操作,而ReLU可以簡(jiǎn)單地通過對(duì)一個(gè)矩陣進(jìn)行閾值計(jì)算得到。
  • 缺點(diǎn):在訓(xùn)練的時(shí)候,ReLU單元比較脆弱并且可能“死掉”。舉例來說,當(dāng)一個(gè)很大的梯度流過ReLU的神經(jīng)元的時(shí)候,可能會(huì)導(dǎo)致梯度更新到一種特別的狀態(tài),在這種狀態(tài)下神經(jīng)元將無法被其他任何數(shù)據(jù)點(diǎn)再次激活。如果這種情況發(fā)生,那么從此所以流過這個(gè)神經(jīng)元的梯度將都變成0。也就是說,這個(gè)ReLU單元在訓(xùn)練中將不可逆轉(zhuǎn)的死亡,因?yàn)檫@導(dǎo)致了數(shù)據(jù)多樣化的丟失。(負(fù)數(shù)沒梯度導(dǎo)致的?)
  • 其實(shí)我個(gè)人一直對(duì)ReLU感覺很奇怪……畢竟這看上去……就是個(gè)線性單元嘛……誰知道他為啥有用,……不過確實(shí)有用

2.4.4 Leaky ReLU

\begin{equation} f(x)=\left\{ \begin{aligned} \alpha x (x<0) \\ 0 (x=0) \\ x (x>0) \\ \end{aligned} \right. \end{equation}
Leaky ReLU是為解決“ReLU死亡”問題的嘗試。其中\alpha為一個(gè)比較小的數(shù)比如0.01.

3. 訓(xùn)練神經(jīng)網(wǎng)絡(luò)

3.1 數(shù)據(jù)預(yù)處理

? ? 在數(shù)據(jù)預(yù)處理中我們有三個(gè)常用記號(hào):數(shù)據(jù)矩陣X,數(shù)據(jù)大小[N \times D],其中N代表樣本數(shù)量,D代表數(shù)據(jù)維度

3.1.1 均值減法(Mean subtraction)

? ? 均值減法(Mean subtraction) 是預(yù)處理最常用的形式。它對(duì)數(shù)據(jù)中每個(gè)獨(dú)立特征減去平均值,從幾何上可以理解為在每個(gè)維度上都將數(shù)據(jù)云的中心都遷移到原點(diǎn)。

3.1.2 歸一化(Normalization)

? ? 歸一化(Normalization) 是指將數(shù)據(jù)的所有維度都?xì)w一化,使其數(shù)值范圍都近似相等。有兩種常用方法可以實(shí)現(xiàn)歸一化。第一種是先對(duì)數(shù)據(jù)做零中心化(zero-centered)(其實(shí)就是上面的均值減法)處理,然后每個(gè)維度都除以其標(biāo)準(zhǔn)差。第二種方法是對(duì)每個(gè)維度都做歸一化,使得每個(gè)維度的最大和最小值是1和-1。但是這個(gè)預(yù)處理操作只有在確信不同的輸入特征有不同的數(shù)值范圍(或計(jì)量單位)時(shí)才有意義。在圖像處理中,由于像素的數(shù)值范圍幾乎是一致的(都在0-255之間),所以進(jìn)行這個(gè)額外的預(yù)處理步驟并不是很必要。


可視化結(jié)果

3.2 權(quán)值初始化

3.2.1 一種錯(cuò)誤的方案:全零初始化

? ?如果我們的權(quán)重是全零的,那么他們的輸出也相同,梯度也相同,什么都是一樣的,這樣用很多神經(jīng)元就沒有意義了。所以,全零初始化是一種錯(cuò)誤的初始化。

3.2.2 隨機(jī)初始化

? ?我們使用很多神經(jīng)元的目的就是為了讓他們各自不一樣,以此來學(xué)習(xí)出不同的特征,加大訓(xùn)練的準(zhǔn)確度,那怎么著就不一樣了呢?干脆隨機(jī)初始化吧。就這樣。但是這樣還會(huì)有一個(gè)不很容易注意到的小問題,在實(shí)踐中會(huì)遇到,我們生成的隨機(jī)數(shù)越多,他們的方差就越大,以常用的Python中的numpy為例,numpy默認(rèn)生成的是高斯分布,他的均值是指定好的,數(shù)字越多,方差自然越大,我們可以這樣做

w = np.random.randn(n) / sqrt(n)

這樣做會(huì)使得生成的方差都為1,使得神經(jīng)網(wǎng)絡(luò)在一開始的時(shí)候每一層生成相似的結(jié)果。實(shí)踐證明,這可以提高收斂速度。

3.3 批量歸一化 Batch Normalization

? ?我們?cè)跀?shù)據(jù)預(yù)處理中介紹了歸一化,Batch Normalization說簡(jiǎn)單了就是在神經(jīng)網(wǎng)絡(luò)內(nèi)部進(jìn)行歸一化處理,比如說



在實(shí)踐中,使用了批量歸一化的網(wǎng)絡(luò)對(duì)于不好的初始值有更強(qiáng)的魯棒性。

3.4 正則化

? ?我們?cè)谥敖榻B過L2正則化,現(xiàn)在,介紹另一種正則化Dropout。
? ?Dropout就是在訓(xùn)練的時(shí)候隨機(jī)廢掉一些節(jié)點(diǎn),相當(dāng)于把網(wǎng)絡(luò)搞小了。用圖片來表示就是這樣的:


? ?核心思路:在訓(xùn)練過程中,隨機(jī)失活可以被認(rèn)為是對(duì)完整的神經(jīng)網(wǎng)絡(luò)抽樣出一些子集,每次基于輸入數(shù)據(jù)只更新子網(wǎng)絡(luò)的參數(shù)(然而,數(shù)量巨大的子網(wǎng)絡(luò)們并不是相互獨(dú)立的,因?yàn)樗鼈兌脊蚕韰?shù))。在測(cè)試過程中不使用隨機(jī)失活,可以理解為是對(duì)數(shù)量巨大的子網(wǎng)絡(luò)們做了模型集成(model ensemble),以此來計(jì)算出一個(gè)平均的預(yù)測(cè)。
? ?需要注意的是,我們?cè)谟?xùn)練的時(shí)候會(huì)規(guī)定一個(gè)參數(shù)
p
,相當(dāng)于廢掉的概率,比如說我們?cè)诘谝浑[藏層廢掉0.4的神經(jīng)元(40%)那么注意的是,在前向inference的時(shí)候,輸出值必須乘以
p = 0.4
,為了和訓(xùn)練的輸出在一個(gè)范圍。或者,在訓(xùn)練的時(shí)候給參數(shù)除以
p
(這是更推薦的方式,因?yàn)椴徽撌欠駪?yīng)用dropout,inference代碼不變)。
? ?Dropout的理解。我一開始看到這個(gè)的時(shí)候,感覺這簡(jiǎn)直就是個(gè)智障級(jí)別的操作,明明那么多神經(jīng)元,非要廢掉一點(diǎn)……真是日了狗了。但是注意,Dropout僅在數(shù)據(jù)量大,網(wǎng)絡(luò)大的情況下適用。想想,去掉一部分確實(shí)就是減少過擬合了(霧)。專業(yè)的解釋可以參考 https://arxiv.org/abs/1506.08700 。

3.5 參數(shù)更新

3.5.1 普通更新

? ?我們都知道,在我們計(jì)算出梯度之后,我們需要更新權(quán)重,權(quán)重更新多少,靠一個(gè)“學(xué)習(xí)率”控制。一般情況下,我們的更新是:x = x - learningrate * dx
其中l(wèi)earning_rate是一個(gè)超參數(shù),它是一個(gè)固定的常量。當(dāng)在整個(gè)數(shù)據(jù)集上進(jìn)行計(jì)算時(shí),只要學(xué)習(xí)率足夠低,總是能在損失函數(shù)上得到非負(fù)的進(jìn)展。

3.5.2 動(dòng)量更新

? ?動(dòng)量(Momentum)更新是另一個(gè)方法,這個(gè)方法在實(shí)踐上幾乎總能得到更好的收斂速度。該方法可以看成是從物理上得到的啟發(fā)。損失值可以理解為是山的高度。用隨機(jī)數(shù)初始化參數(shù)等同于在某個(gè)位置給質(zhì)點(diǎn)設(shè)定初始速度為0。這樣最優(yōu)化過程可以看做是模擬參數(shù)(即質(zhì)點(diǎn))在山上滾動(dòng)的過程。
? ?因?yàn)樽饔糜谫|(zhì)點(diǎn)的力與梯度的潛在能量有關(guān),質(zhì)點(diǎn)所受的力就是損失函數(shù)的負(fù)梯度。還有,因?yàn)椋栽谶@個(gè)觀點(diǎn)下負(fù)梯度與質(zhì)點(diǎn)的加速度是成比例的。注意這個(gè)理解和上面的隨機(jī)梯度下降(SDG)是不同的,在普通版本中,梯度直接影響位置。而在這個(gè)版本的更新中,物理觀點(diǎn)建議梯度先影響速度,然后速度再影響位置:
v = mu * v - learningrate * dx
x = x + v

? ?在這里引入了一個(gè)初始化為0的變量v和一個(gè)超參數(shù)mu。說得不恰當(dāng)一點(diǎn),這個(gè)變量(mu)在最優(yōu)化的過程中被看做動(dòng)量(一般值設(shè)為0.9),但其物理意義與摩擦系數(shù)更一致。這個(gè)變量有效地抑制了速度,降低了系統(tǒng)的動(dòng)能,不然質(zhì)點(diǎn)在山底永遠(yuǎn)不會(huì)停下來。通過交叉驗(yàn)證,這個(gè)參數(shù)通常設(shè)為[0.5,0.9,0.95,0.99]中的一個(gè)。和學(xué)習(xí)率隨著時(shí)間退火(下文有)類似,動(dòng)量隨時(shí)間變化有時(shí)能略微改善優(yōu)化的效果,其中動(dòng)量在學(xué)習(xí)過程的后階段會(huì)上升。一個(gè)典型的設(shè)置是剛開始將動(dòng)量設(shè)為0.5而在后面的多個(gè)訓(xùn)練輪次中慢慢提升到0.99。

3.5.3 Nesterov動(dòng)量更新

? ?Nesterov動(dòng)量更新說實(shí)話我沒怎么看明白他到底想講什么意思……有時(shí)間看論文原文再回來填坑吧。
v_{pre} = v
v = mu * v ‐ learningrate * dx
x =x ‐mu * v_{pre} + (1 + mu) * v

3.5.4 學(xué)習(xí)率退火

? ?我們?cè)谥耙呀?jīng)提到過,學(xué)習(xí)率過大會(huì)導(dǎo)致在訓(xùn)練后期網(wǎng)絡(luò)難以收斂,在最優(yōu)解附近跳來跳去,為了解決這個(gè)問題,我們將使學(xué)習(xí)率不斷下降,常用的有兩種。

  • 指數(shù)衰減:\alpha = \alpha_0e^{-kt}其中k是超參數(shù),t是迭代次數(shù)
  • 1/t衰減:\alpha = \frac{\alpha_0}{1 + kt}其中k是超參數(shù),t是迭代次數(shù)

3.5.5 逐參數(shù)適應(yīng)學(xué)習(xí)率方法

我們前面討論的方案都是對(duì)全局學(xué)習(xí)率進(jìn)行操控,但是,我們知道,神經(jīng)網(wǎng)絡(luò)每一點(diǎn)都是不同的,如果我們對(duì)每個(gè)參數(shù)都用不同的學(xué)習(xí)率怎么樣呢?
下面為了方便(懶得打公式,下面的式子寫成寫程序都簡(jiǎn)單,寫公式麻煩的一比)
下面的結(jié)論都是沒有推導(dǎo)的(如果我看視頻沒走神的話),想看可以找原論文看

3.5.5.1 Adagrad
cache += dx**2
x += ‐ learning_rate * dx / (np.sqrt(cache) + eps)

其中eqs一般設(shè)置為[0.000000001,0.0001]防止除0。

3.5.5.2 RMSprop
cache = decay_rate * cache + (1 ‐ decay_rate) * dx**2
x += ‐ learning_rate * dx / (np.sqrt(cache) + eps)

decay_rate是一個(gè)超參數(shù),常用的值是[0.9,0.99,0.999]。

3.5.5.3 Adam
m = beta1*m + (1‐beta1)*dx
v = beta2*v + (1‐beta2)*(dx**2)
x += ‐ learning_rate * m / (np.sqrt(v) + eps)

RMSProp的動(dòng)量版【滑稽.jpg】推薦的參數(shù)值eps=0.00000001, beta1=0.9, beta2=0.999

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容