cs31n_lesson6_7

1.生物學解釋

神經網絡中的神經元(neurons):從輸入(如圖像)得到的一個輸出最小單元稱之爲一個神經元。具體一點說,對於一個雙層網絡(1輸入、1中間層、1輸出),如果輸入爲一個樣本,則隱藏層的維數H+最終輸出維度數C,就是神經元的個數。一個神經元包括所需要的所有參數;包括一組wij(i=0,,D) ,b,以及激活函數這幾個參數。比如XNXDWDXC 中,wii=0,,,D)

樹突:x0
軸突:w0x1
The idea is that the synaptic strengths (the weights ww) are learnable and control the strength of influence (and its direction: excitory (positive weight) or inhibitory (negative weight)) of one neuron on another.當累加到一定程度後,輸出激活(由激活函數控制),將輸出傳到下一個神經元的突觸(wnext

由於算出結果只是一個標量,所以一個神經元的輸出可以處理成概率(如softmax等),可以進行對一幅圖進行二分類。
SVM可以看做是單層神經網絡(沒有中間層,只有輸入輸出層,由於不必考慮輸入,所以是單層)。

2.圖像數據預處理

零中心值化的作用:
由於對W求導數是xi ,如果恆爲正或恆爲負,則梯度下降的方向是同一個方向,最終可能無法朝着優化的方向前進。

如圖,我們需要不同方向的x(紅色),來使得最終的下降方向接近最優方向(藍色)圖:
這裏寫圖片描述

具體做法是(灰度圖)減去所有值的平均值,或(彩色圖)RGB等channel分別減去各自channel的平均值。也可以從train數據中選一批圖像來做訓練。

PCA and Whitenning
如圖,對於輸入圖像xi和xj,他們的協方差矩陣爲:
所以PCA預處理過程爲

# Assume input data matrix X of size [N x D]
X -= np.mean(X, axis = 0) # zero-center the data (important)
cov = np.dot(X.T, X) / X.shape[0] # get the data covariance matrix

由於cov是半正定的,對其進行svd分解,可以得到特徵向量U,U各個維度相互正交。然後可以對數據進行去耦合,所謂去耦合,直觀上是將數據進行一定旋轉,具體方法是將各個數據維度投影到/乘上新的座標軸U(得到結果如中間的圖,x軸與y軸整體上已經沒有相關性):

U,S,V = np.linalg.svd(cov)
Xrot = np.dot(X, U) # decorrelate the data

同時由於U已經按照對應特徵值的權重進行了排序,因此我們可以選擇前n個權重較大的軸/維度,捨棄剩下部分,以達到降維目的。

Xrot_reduced = np.dot(X, U[:,:100]) # Xrot_reduced becomes [N x 100]

將這些數據歸一化(除以各自座標軸的權重),同時爲了避免權重爲0,可以加上一個白噪聲處理。【在降低維度階段就消除這些爲0或過小的維度?】

Xwhite = Xrot / np.sqrt(S + 1e-5)

整個過程相當於消除了低頻信號(圖像中梯度比較小的部分),增強高頻信號(特徵點、線)。

Batch Normalization
如果在每一層輸入的時候,先加個預處理操作,比如網絡第三層輸入數據X3(X3表示網絡第三層的輸入數據)把它歸一化至:均值0、方差爲1,然後再輸入第三層計算,這樣我們就可以解決前面所提到的“Internal Covariate Shift”的問題了。一般講BN放在全連接層和非線性函數之間
如圖:
這裏寫圖片描述
如果認爲每個輸入都需要在相同的scale區間(比如[-1,1]),如不同圖片的光照條件差別很大,則可以對圖像進行normalization.
normalization的好處:
提高梯度平滑度;
減少強相關;
可以使用更高的學習率;

再說兩句

一般預處理是隻對train數據進行零均值化,得到的均值用來處理validation和test數據。

3.初始化

由於反向傳播時對x的梯度就是w,所以w需要進行一些初始化,一般認爲w應該整體上以0對稱分佈,同時不能太大,也不能太小。如果認爲輸入和結果都滿足標準高斯分佈的話,那麼w的方差即是1/n,則標準差/平均值爲1/sqrt(n)
所以對於類似tanh的激活函數,一般初始化成:

W=np.random.randn(fanin,fanout)/np.sqrt(fanin/2)

fanin,fanout 分別是該層輸入和輸出的個數。
而對於Relu函數,由於分佈不同,一般初始化爲:
w = np.random.randn(n) * sqrt(2.0/n)

此外還有隨機遊走、數據關聯等方法來初始化。
而對b來說,一般初始化爲0.

4.正則化

正則化的λ ,意味着每次更新都要減去λW
L1和L2正則化的使用區別
L1會導致一個比較稀疏的結果,也就是最終的w使得該系統更青睞於那些更重要高的輸入;相比之下L2更容易導致一個比較均勻的w。如果無法明確知道輸入有明顯的feature特性,就用L2吧。
Max norm constraints
即對w元素的最大值進行上界限制。
Dropout
在訓練時用一個概率p來丟棄某些參數,比如
H1*(np.random.rand(*H1.SHAPE)

5.調參

對於一個給定的模型框架,需要調試的參數包括:最初的學習率,學習率下降框架,正則項權重,droput項參數;對於一個給定的工作,需要的調參還包括初始值,訓練次數,神經網絡總層數包括每層的神經元個數
在設計程序時,需要設計一個worker部分來不斷地嘗試不同參數並記錄並輸出最終結果(時間、精確度等)到文件,同時一些worker在validation上驗證最終結果;並同時設計一個master來開啓或殺掉集羣中的這些workers.
先不加正則項來測試loss和grad;單獨調正則項確定它的權重,
確定grad沒問題時,現在一個小集合上訓練:
loss not going down:
- learning rate too low
loss exploding:
- learning rate too high
同時,需要調:
不同的初始化
coarse to fine:先挑一小部分數據跑,再在所有數據上跑;如故loss>3*original_cost
Prefer random search to grid search

梯度檢查:

對2層網絡來說:
relative error > 1e-2 usually means the gradient is probably wrong
but usually means the gradient is probably wrong
relative error < 1e-4 OK
but if ther are activation function, then relative error <1e-7 may be ok.
對多層網絡來說:
深度越深,可容納的誤差越大,比如10層網絡,1e-2可能就差不多了。

調學習率

x += -learning_rate * dx;#一般情況

Momentum update(動量下降):

直觀上我們能感受到整個下降過程的斜率變化越來越小,所以可以近似看做是一個減速運動模型

v = mu * v -learning_rate * dx
x += v

mu即是動量momentum,是一個待調試的hyperparameter(常常在0.9左右,所以常常在交叉驗證時設置爲[0.5,0,9,0.95,0.99])
動量下降可以極大加快下降速度

Nesterov Momentum

x_ahead = x + mu * v
# evaluate dx_ahead     (the gradient at x_ahead instead of at x)
v = mu * v - learning_rate * dx_ahead
x += v

mu越大,表示越相信之前的迭代速度,也就是慣性越大

x_ahead = x + mu * v
dx = ....#calculate the gradient based ahead x.
v_prev = v # back this up
v = mu * v - learning_rate * dx # velocity update stays the same
x += mv*(v- v_prev) + v # position update changes form

AdaGrad (不常用)

相當於對之前的”速度”,也就是梯度,求平均值,那麼隨着梯度降低,最後的梯度也會越來越小沒速度也越來越小。假如有很多局部最優解呢,AdaGrad隨着時間,速度快速下降的特性會侷限在局部最優解中。下面是對它的改進

RMSProp

將上一次梯度下降速度融入到當前速度中,這樣會減緩速度的下降。

Adam(最常用)

相當於對(某個變量)下降速度和下降梯度平方之間進行一個權衡,使得變量迭代得更加平滑。此處的first_moment相當於下降速度,第二個相當於下降速度的速度。初值設置時需要注意:不能將moment2的初值設爲0,而要設一個很小的正數。
否則第一次迭代後分母過大會導致x的步長太大
此外還有變種:Adamax,Nadam
還有一種全的方法
Adam比較常用

annealing/decay the learning rate(降低學習率)

有單步降低:a_{i+1} = a_0 - t * decay_a#t 是迭代次數  
指數降低:
a = a_0* e^{-kt}1/t a = a_0/(1+kt)$
常用的是單步降低,先跑一遍,得到一個比較合適的a,再降低decay_a來進一步得到合適的a。

可以先不用學習率的decay,看看下降情況,再使用上述各種decay方法。

L-BFGS(目前比較popular的limited memory的擬牛頓方法)

在相比小數據集,它在大數據集上表現比較好,也就是需要在很大的batch上甚至全局上進行計更新算;在非凸問題上表現不佳

根據結果繼續調參

過擬合

如果train精度與test精度的gap過大,則可能存在過擬合:
更深層的網絡容易出現過擬合現象,數據稀少也會造成過擬合。
- 使用淺層的網絡
- 增加訓練數據嗎,或者增加訓練/測試數據的比值
- 增加正則項權重
- 更多的dropout來阻止過擬合
- batch normalization
- data augmentation(即生成更多樣性的數據,比如一個貓的鏡像、平移、旋轉等等)
- max pooling
- 殘差網絡
一般先使用batch normalization,如果還不足夠,則加上其他功能。

如果模板比較模糊,可能是

最後模型集成(model ensembles)

模型集成有助於利用不同的參數
可以通過不同的方式訓練形成10個不同的model,然後將這些model加起來取平均值得到的效果可能好於一個model.
不同的模板的方法有
- 單一模型但不同的初始化;
- 通過交叉驗證在不同數據集上生成的模型;
- 每個模型之後設置不同的checkponits

transfer trainning

如果數據量很小,可以先看做類似目標(如分類)的已經訓練好的模型在數據也很相似的很大的數據上的參數。由於自己處理的任務可能只是它的任務的子集(比如它分成1000類,我只分成10類)以及自己數據量也比較小,自己可以只調這個模型的部分層的參數(如頭幾層):圖:

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