深度學習筆記(1)——神經網絡詳解及改進

前言

筆者一直在ipad上做手寫筆記,最近突然想把筆記搬到博客上來,也就有了下面這些。因爲本是給自己看的筆記,所以內容很簡陋,只是提了一些要點。隨緣更新。

正文

step1 建立一個神經網絡模型

一個常見的神經網絡——完全連接前饋神經網絡
  • 全連接:layer和layer之間兩兩連接
  • 前饋傳遞方向由後向前,任意兩層之間沒有反饋
  • 深度:許多隱含層

σ([1211][11]+[10])=[0.980.12]\sigma(\begin{bmatrix}1&-2 \\-1&1\end{bmatrix}\begin{bmatrix}1 \\-1\end{bmatrix}+\begin{bmatrix}1 \\0\end{bmatrix})=\begin{bmatrix}0.98 \\0.12\end{bmatrix} 如此一層一層傳遞下去。

最普通的激活函數σ(z)\sigma(z)爲sigmoid函數
f(z)=11+ezf(z)=\frac{1}{1+e^{-z}}

其圖像爲:

當然,現在已經很少使用sigmoid函數做激活函數了。

本質

通過隱含層來代替原來的特徵工程,這樣最後一個隱含層輸出的就是一組新的特徵,然後通過一個多分類器(可以是solfmaxsolfmax函數)得到最後的輸出yy。因爲並不是每種數據都是結構化的,例如圖片、語音這種,這類數據是非結構的,人們很難通過各種特徵對其進行有效的特徵處理,所以傳統的機器學習在這種領域將不再適用。於是人們想出了這種通過一層層的隱含層對其進行強制擬合的模型,稱之爲神經網絡。

舉例:手寫識別

step2 模型評估

對於神經網絡,我們採用交叉熵來對 yyy^\hat y 的損失進行計算。(後期我將在生成模型和判別模型中對他進行詳細的描述)

step3 最佳模型——梯度下降

backpropationbackpropation(反向傳播,也就是所謂的BPBP)在神經網絡中是一種有效的方式計算Lw\frac{\partial{L}}{\partial w}的方式,我們可以利用很多框架進行計算,如:TensorFlow,Pytorch。

反向傳播(BPBP)

L(θ)L(\theta)是總體損失函數,ln(θ)l^n(\theta)是單個樣本產生的誤差。

計算L(θ)=n=0Nln(θ)L(\theta)= \sum_{n=0}^{N}l^n(\theta),只需要計算L(θ)w=n=1NL(θ)w\frac{\partial L(\theta)}{\partial w}=\sum_{n=1}^{N}\frac{\partial L(\theta)}{\partial w}

我們取出一個神經元進行分析

易得:
lw=zwlz\frac{\partial l}{\partial w}=\frac{\partial z}{\partial w}\frac{\partial l}{\partial z}

Forward Pass zw\frac{\partial z}{\partial w}:

這裏我可以很輕鬆看出zw\frac{\partial z}{\partial w}爲上一隱含層輸出的值。

Backward Pass lz\frac{\partial l}{\partial z}:

lz=azla=az[zalz+zalz]=σ(z)[w3lz+w4lz]\frac{\partial l}{\partial z}=\frac{\partial a}{\partial z}\frac{\partial l}{\partial a} = \frac{\partial a}{\partial z}[\frac{\partial z'}{\partial a}\frac{\partial l}{\partial z}+\frac{\partial z''}{\partial a}\frac{\partial l}{\partial z''}] = \sigma'(z)[w_3 \frac{\partial l}{\partial z'} + w_4 \frac{\partial l}{\partial z''}]

這時候我們會覺得每計算一次梯度相當麻煩,每個參數的梯度都需要層層往後計算,計算量大到無法想象。實際上進行Backward Pass和向前傳播的計算量差不多,我們只需將我們的思維逆轉一下,從最後一層往前計算,也能計算出所有參數的梯度,這時的計算量是線性的,這就是 BPBP 的思想(個人爲很類似於算法中的動態規劃)。

利用keras建立神經網絡

建立神經網絡的過程,別人以爲你在搞什麼特別深奧高大上的東西,其實你只是在搭積木一樣一層一層疊隱含層而已=。=

import keras
from keras.models import Sequential
from keras.layers import Dense

model = Sequential()    # 建立一個模型
# 搭建網絡
'''@param
    Dense: Fully connect layer
    input_dim: 輸入層
    units: 神經元
    activation: 激活函數
'''
model.add(Dense(input_dim=10, units=500, activation='sigmoid'))   # 建立一個神經網絡
# 再加一個隱含層
model.add(Dense(units=500, activation='sigmoid'))
# 輸出層
model.add(Dense(units=10, activation='softmax'))    # 輸出向量長度爲10,激活函數爲softmax
# loss function
model.compile(loss='categotial_crossentropy',  # 損失函數:交叉熵
              optimizer='adam',  # 優化器(都是梯度下降)
              metrics=['accuracy']  # 指標
              )
# batch_size: 將訓練集隨機分爲分爲幾個batch,每次計算隨機的一個
# 所有batch都計算一次,一個epoch結束
model.fit(x_train, y_train, batch_size=100, epochs=20)

# case1: 測試集正確率
score = model.evaluate(x_test, y_test)
print('Total loss on Test Set:', score[0])
print('Accuracy of Testing Set:', score[1])
# case 2:模型預測
result = model.predict(x_test)

深度學習的技巧

在test上如何改進:

新的激活函數

sigmoid缺點——梯度消失:

有時神經網絡層數越深,結果越差,原因可能是梯度消失,比較靠近input的幾層梯度很小,靠近output的幾層梯度較大,在前幾層還未怎麼更新參數時,後幾層已經收斂。因爲每經過一個sigmoid,Δw\Delta w的影響就會被消弱。

ReLU:
  • 當 input > 0 時,output = input
  • 當 input < 0 時,output = 0

在input < 0 時,相當於該節點被移除,整個網絡就是 a thinner linear network,如果時線性的話,梯度不會遞減。
你可能會說這個線性模型如何處理那些複雜的非線性模型,畢竟不是所有問題都和線性一樣美好,你要注意了我們這是deep learning,關鍵在於這個“deep”,這是一個有着數層幾千個神經元的網絡,它們疊加的效果就是一個非線性的模型,是一個很複雜的function。對於ReLU activation function的神經網絡,只是在小範圍內是線性的,在總體上還是非線性的。

好處:

  1. 比sigmoid處理起來快
  2. 無窮多的sigmoid疊加起來的結果(不同的bias)
  3. 可以處理梯度消失

變種:

  • Leaky ReLU

  • Parametric ReLU

Maxout —— 讓network自動學習的激活函數

方法:

  1. 先將輸入分組,如2個一組或3個一組
  2. 再從每一組中選擇最大的一個

下圖爲一個簡單的示例

原理:
其實上面介紹的ReLU爲一個特殊的Maxout,理論上Maxout可以擬合任何激活函數
比如下面這個ReLU可以由如此的Maxout得到

選擇不同的wwbb可以做到

你可能會問這樣不就有的節點訓練不到了嗎?因爲有些節點的權值爲0等於從網絡中去除了。其實只是部分數據上此節點爲0,但是我們有大量數據,總有數據可以訓練到這個節點。所以 MaxoutMaxout 需要比 ReLUReLU 更大的數據量才能訓練好這個網絡。

更新學習速率

RMSProp

屬於之前在線性模型中提到的AdagradAdagrad算法的變形
w1w0ησ0g0σ0=g0w^1 \longleftarrow w^0 - \frac{\eta}{\sigma^0}g^0 \qquad \sigma^0=g^0
w2w1ησ1g1σ1=α(σ0)2+(1α)(g1)2w^2 \longleftarrow w^1 - \frac{\eta}{\sigma^1}g^1 \qquad \sigma^1=\sqrt{\alpha(\sigma^0)^2+(1-\alpha)(g^1)^2}
w3w2ησ2g2σ2=α(σ1)2+(1α)(g2)2w^3 \longleftarrow w^2 - \frac{\eta}{\sigma^2}g^2 \qquad \sigma^2=\sqrt{\alpha(\sigma^1)^2+(1-\alpha)(g^2)^2}
............
wt+1wtησtgtσt=α(σt1)2+(1α)(gt)2w^{t+1} \longleftarrow w^t - \frac{\eta}{\sigma^t}g^t \qquad \sigma^t=\sqrt{\alpha(\sigma^{t-1})^2+(1-\alpha)(g^t)^2}

一個固定的learning rate除以一個σ\sigma(在第一個時間點,σ\sigma就是第一個算出來GD的值),在第二個時間點,你算出來一個g1g^1σ2\sigma^2(你可以去手動調一個α\alpha值,把α\alpha值調整的小一點,說明你傾向於相信新的gradient告訴你的這個error surface的平滑或者陡峭的程度)。

Momentum

參考了物理世界慣性的概念,遇到一個小山坡時可以通過慣性翻過,從而越過局部最優點。

在算法中只參考上一次的速度,因爲上一次的速度已經包含了之前所有的速度。
步驟:

  1. 選擇一個初始位置 θ0\theta^0 和初始速度 v0=0v^0=0
  2. 計算在 θ0\theta^0 處的梯度ΔL(θ0)\Delta L(\theta^0)
  3. v1=λv0ηΔL(θ0)v^1=\lambda v^0-\eta\Delta L(\theta^0)
  4. θ0=θ1+v1\theta^0= \theta^1+v^1
  5. 如此往復
Adam

RMSPropRMSPropMomentumMomentum的結合。有興趣的朋友直接看圖吧。

在這裏插入圖片描述

在train上改進(過擬合)

Early Stopping

我們需要的是測試集錯誤最小,而不是訓練集,如果測試集的Loss上升,則需要立刻停止訓練,但是如果將測試集加入訓練則會導致測試結果不客觀。這時我們可以引入驗證集來解決。當訓練時驗證集Loss上升則停止訓練。

Regularization

和線性模型一樣,我們需要在原來的lossfunctionloss function加入正則化,讓得到的結果更加平滑。
常見的有L1normL_1-norm(一次式)和L2normL_2-norm(二次式)

Dropout
如何訓練

在訓練時的時候,每一次參數更新之前,對network裏面的每個神經元(包括輸入層),做採樣(sampling)。 每個神經元會有p%的可能性會被丟掉,跟着的 ww 也會被丟掉。

解釋

你在訓練時,加上dropout,你會看到在訓練集上結果會變得有點差(因爲某些神經元不見了),但是dropout真正做的事就是讓你測試集越做越好。

假設有mm個神經元,就可以訓練 2m2^m 個神經網絡結構,每個網絡的偏差雖然很大,但是最後平均下來還是很準的(這個又要回到我們在線性模型中說的 variencevariencebiasbias 問題)。

dropout其實是用了模型融合(model essemble)的思想,訓練了很多模型最後加權得到最終的結果。

在testing上注意兩件事情:
  • 第一件事情就是在testing上不做dropout。
  • 在dropout的時候,假設dropout rate在training是p%,all weights都要乘以(1p%)(1-p\%)

關於爲什麼要乘(1p%)(1-p\%),舉一個簡單的例子:

總結

到此神經網絡已經介紹得差不多了,你可能會說,就這,就這?其實神經網絡也不是什麼深奧的東西,本質上就是一個有着數千個參數的模型,和最簡單的線性模型一樣,也是通過最常規的方法——梯度下降求解。當然,其中也涉及了一些挺玄學(只可意會,不可言傳,當然也是我的數學功底不夠,無法準確描述)的方法。

上一篇:機器學習筆記(1)——線性迴歸
下一篇:可能會講一講CNN或者神經網絡中神經元的來源——logistic迴歸(未開始寫=。=)

(如果覺得有用請點個贊吧)

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