前言
筆者一直在ipad上做手寫筆記,最近突然想把筆記搬到博客上來,也就有了下面這些。因為本是給自己看的筆記,所以內容很簡陋,只是提了一些要點。隨緣更新。
正文
step1 建立一個神經網絡模型
一個常見的神經網絡——完全連接前饋神經網絡
- 全連接:layer和layer之間兩兩連接
- 前饋傳遞方向由后向前,任意兩層之間沒有反饋
- 深度:許多隱含層
\(\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}\) 如此一層一層傳遞下去。
最普通的激活函數\(\sigma(z)\)為sigmoid函數
其圖像為:
當然,現在已經很少使用sigmoid函數做激活函數了。
本質
通過隱含層來代替原來的特征工程,這樣最后一個隱含層輸出的就是一組新的特征,然后通過一個多分類器(可以是\(solfmax\)函數)得到最后的輸出\(y\)。
舉例:手寫識別
step2 模型評估
對於神經網絡,我們采用交叉熵來對 \(y\) 和 \(\hat y\) 的損失進行計算。(后期我將在生成模型和判別模型中對他進行詳細的描述)
step3 最佳模型——梯度下降
\(backpropation\)(反向傳播,也就是所謂的\(BP\))在神經網絡中是一種有效的方式計算\(\frac{\partial{L}}{\partial w}\)的方式,我們可以利用很多框架進行計算,如:TensorFlow,Pytorch。
反向傳播(\(BP\))
\(L(\theta)\)是總體損失函數,\(l^n(\theta)\)是單個樣本產生的誤差。
計算\(L(\theta)= \sum_{n=0}^{N}l^n(\theta)\),只需要計算\(\frac{\partial L(\theta)}{\partial w}=\sum_{n=1}^{N}\frac{\partial L(\theta)}{\partial w}\)。
我們取出一個神經元進行分析
易得:
Forward Pass \(\frac{\partial z}{\partial w}\):
這里我可以很輕松看出\(\frac{\partial z}{\partial w}\)為上一隱含層輸出的值。

Backward Pass \(\frac{\partial l}{\partial z}\):
這時候我們會覺得每計算一次梯度相當麻煩,每個參數的梯度都需要層層往后計算,計算量大到無法想象。實際上進行Backward Pass和向前傳播的計算量差不多,我們只需將我們的思維逆轉一下,從最后一層往前計算,也能計算出所有參數的梯度,這時的計算量是線性的,這就是 \(BP\) 的思想(個人為很類似於算法中的動態規划)。
利用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,\(\Delta w\)的影響就會被消弱。
ReLU:
- 當 input > 0 時,output = input
- 當 input < 0 時,output = 0
在input < 0 時,相當於該節點被移除,整個網絡就是 a thinner linear network,如果時線性的話,梯度不會遞減。
你可能會說這個線性模型如何處理那些復雜的非線性模型,畢竟不是所有問題都和線性一樣美好,你要注意了我們這是deep learning,關鍵在於這個“deep”,這是一個有着數層幾千個神經元的網絡,它們疊加的效果就是一個非線性的模型,是一個很復雜的function。對於ReLU activation function的神經網絡,只是在小范圍內是線性的,在總體上還是非線性的。
好處:
- 比sigmoid處理起來快
- 無窮多的sigmoid疊加起來的結果(不同的bias)
- 可以處理梯度消失
變種:
-
Leaky ReLU

-
Parametric ReLU

Maxout —— 讓network自動學習的激活函數
方法:
- 先將輸入分組,如2個一組或3個一組
- 再從每一組中選擇最大的一個
下圖為一個簡單的示例

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

選擇不同的\(w\)和\(b\)可以做到

你可能會問這樣不就有的節點訓練不到了嗎?因為有些節點的權值為0等於從網絡中去除了。其實只是部分數據上此節點為0,但是我們有大量數據,總有數據可以訓練到這個節點。所以 \(Maxout\) 需要比 \(ReLU\) 更大的數據量才能訓練好這個網絡。
更新學習速率
RMSProp
屬於之前在線性模型中提到的\(Adagrad\)算法的變形
一個固定的learning rate除以一個\(\sigma\)(在第一個時間點,\(\sigma\)就是第一個算出來GD的值),在第二個時間點,你算出來一個\(g^1\)和 \(\sigma^2\)(你可以去手動調一個\(\alpha\)值,把\(\alpha\)值調整的小一點,說明你傾向於相信新的gradient告訴你的這個error surface的平滑或者陡峭的程度)。
Momentum
參考了物理世界慣性的概念,遇到一個小山坡時可以通過慣性翻過,從而越過局部最優點。

在算法中只參考上一次的速度,因為上一次的速度已經包含了之前所有的速度。
步驟:
- 選擇一個初始位置 \(\theta^0\) 和初始速度 \(v^0=0\)
- 計算在 \(\theta^0\) 處的梯度\(\Delta L(\theta^0)\)
- \(v^1=\lambda v^0-\eta\Delta L(\theta^0)\)
- \(\theta^0= \theta^1+v^1\)
- 如此往復
Adam
\(RMSProp\)和\(Momentum\)的結合。有興趣的朋友直接看圖吧。

在train上改進(過擬合)
Early Stopping
我們需要的是測試集錯誤最小,而不是訓練集,如果測試集的Loss上升,則需要立刻停止訓練,但是如果將測試集加入訓練則會導致測試結果不客觀。這時我們可以引入驗證集來解決。當訓練時驗證集Loss上升則停止訓練。
Regularization
和線性模型一樣,我們需要在原來的\(loss function\)加入正則化,讓得到的結果更加平滑。
常見的有\(L_1-norm\)(一次式)和\(L_2-norm\)(二次式)
Dropout
如何訓練
在訓練時的時候,每一次參數更新之前,對network里面的每個神經元(包括輸入層),做采樣(sampling)。 每個神經元會有p%的可能性會被丟掉,跟着的 \(w\) 也會被丟掉。
解釋
你在訓練時,加上dropout,你會看到在訓練集上結果會變得有點差(因為某些神經元不見了),但是dropout真正做的事就是讓你測試集越做越好。
假設有\(m\)個神經元,就可以訓練 \(2^m\) 個神經網絡結構,每個網絡的偏差雖然很大,但是最后平均下來還是很准的(這個又要回到我們在線性模型中說的 \(varience\) 和 \(bias\) 問題)。
dropout其實是用了模型融合(model essemble)的思想,訓練了很多模型最后加權得到最終的結果。

在testing上注意兩件事情:
- 第一件事情就是在testing上不做dropout。
- 在dropout的時候,假設dropout rate在training是p%,all weights都要乘以\((1-p\%)\)
關於為什么要乘\((1-p\%)\),舉一個簡單的例子:

總結
到此神經網絡已經介紹得差不多了,你可能會說,就這,就這?其實神經網絡也不是什么深奧的東西,本質上就是一個有着數千個參數的模型,和最簡單的線性模型一樣,也是通過最常規的方法——梯度下降求解。當然,其中也涉及了一些挺玄學(只可意會,不可言傳,當然也是我的數學功底不夠,無法准確描述)的方法。
上一篇:機器學習筆記(1)——線性回歸
下一篇:可能會講一講CNN或者神經網絡中神經元的來源——logistic回歸(未開始寫=。=)
(如果覺得有用請點個贊吧)
