1. 程式人生 > >深度神經網路訓練的技巧

深度神經網路訓練的技巧

這裡主要介紹8中實現細節的技巧或tricks:資料增廣、影象預處理、網路初始化、訓練過程中的技巧、啟用函式的選擇、不同正則化方法、來自於資料的洞察、整合多個深度網路的方法。

1.       資料增廣

在不改變影象類別的情況下,增加資料量,能提高模型的泛化能力


自然影象的資料增廣方式包括很多,如常用的水平翻轉(horizontally flipping),一定程度的位移或者裁剪和顏色抖動(color jittering)。此外還可以嘗試多種操作的組合, 例如同時做旋轉和隨機尺度變換,此外還可以把每個patch中所有畫素在HSV顏色空間中的飽和度和明度提升0.25-4次冪方,乘以0.7-1.4之間的一個因子,再加一個-0.1-0.1之間的值。同樣你可以在色調通道(H)對每張圖片或patch的所有畫素增加一個-0.1-0.1之間的值。(未完待續。。。。。。。。)

2.      預處理

2.1最簡單的預處理方法:零均值化(zero-center)和標準化(normalize)

2.1.1為什麼要零均值化(Mean Subtraction)?

資料有過大的均值可能導致引數的梯度過大,如果有後續的處理,可能要求資料零均值,比如PCA。零均值化並沒有消除畫素之間的相對差異,人們對影象資訊的攝取通常來自於畫素之間的相對色差,而不是畫素值的高低。

2.1.2為什麼歸一化(Normalization)?

歸一化是為了讓不同維度的資料具有相同的分佈。

假如二維資料(X1,X2)兩個維度都服從均值為零的正態分佈,但是X1方差為100,X2方差為1。那麼對(X1,X2)進行隨機取樣在二維座標系中繪製的影象,應該是狹長的橢圓形。

對這些資料做特徵提取會用到以下形式的表示式:S = w1*x1 + w2*x2 + b

那麼引數W1,W2的梯度為:dS / dW1 = x1          dS/ dw2 = x2

由於x1與x2在分佈規模上的巨大差異,w1與w2的導數也會差異巨大。此時繪製目標函式(不是S)的曲面圖,就像一個深邃的峽谷,沿著峽谷方向變化的是w2,坡度很小;在峽谷垂直方向變化的是w1,坡度非常陡峭,如圖1,而我們期望的目標函式是圖2這樣的。

目標函式是非常難以優化的,因為w1和w2的梯度差異太大,所以在兩個維度上需要不同的迭代方案。但在實際操作中,為了方便,我們通常為所有維度設定相同的步長,隨著迭代的進行,步長的縮減在不同維度也是同步的。這就要求w不同緯度的分佈規模大致相同,而這一切都始於資料的歸一化。

2.1.3實現程式碼

X-=numpy.mean(X,axis=0) #即X的每一列都減去該列的均值

注:對於灰度影象,零均值化也可以減去整張圖片的均值:X-=numpy.mean(X)

X/=numpy.std(X,axis=0) #資料歸一化。

X是輸入資料,(圖片數目X圖片維度)。另一種標準化(normalize)方式是標準化每個維度,保證每個維度的最大值和最小值是-1和1。

這種預處理的方式只在輸入的各個特徵的尺度或者單位不同時才有意義。以圖片畫素作為輸入為例子,所有畫素值尺度都在0-255這個尺度之間,所以沒必要嚴格的執行這種預處理操作。在自然影象上進行訓練時,可以不進行歸一化操作,因為理論上影象任一部分的統計性質都應該和其他部分相同,影象的這種特性被稱作平穩性(stationarity)

2.2另一種預處理方式是PCA&Whitening(白化)。

白化相當於在零均值化和歸一化操作之間插入一個旋轉操作,將資料投影到主軸上。一張圖片經過白化後,可以認為每個畫素之間是統計獨立的。然而白化很少在卷積神經網路中使用,可能原因是影象資訊本來就是依靠畫素之間的相對差異來體現的,白化讓畫素間去相關,讓這種差異變得不確定,損失了資訊。

首先將資料零均值化,再計算協方差矩陣(convariance matrix)來觀察資料中的相關結構。

X-=np.mean(X,axis=0)

cov=np.dot(X.T,X)/X.shape[0] #計算協方差矩陣

然後做去相關操作,即通過將原始資料(零均值化後的資料)投影到特徵基空間(eigenbasis)。

U,S,V=np.linalg.svd(cov) #計算資料協方差矩陣的奇異值分解(SVDfactorization)

Xrot=np.dot(X,U) #對資料去相關

最後一步變換是白化,即把特徵基空間的資料除以每個維度的特徵值來標準化尺度。

Xwhite=Xrot/np.sqrt(S+1e-5) #除以奇異值的平方根,注意到這裡加了個1e-5(也可以是其他小的常量)是為了防止分母是0的情況。

PCA白化的一個缺點是會增加資料中的噪聲,因為它把輸入資料的所有維度都延伸到相同的大小,這些維度中就包含噪音維度(往往表現為不相關的且方差較小)。這種缺點在實際操作中可以通過把1e-5增大到一個更大的值來引入更強的平滑。

3.初始化

3.1不要將引數全部初始化為零

幾乎所有的CNN網路都是堆成結構,將引數零初始化會導致流過網路的資料也是對稱的(都是零),並且沒有辦法在不受擾動的情況下打破這種資料對稱,從而導致網路無法學習。

引數零初始化時,無論輸入是什麼,中間神經元的啟用值都是相同的(任意一個神經元的啟用值a=f(WTX),當權重W是零向量時,WTX也是零向量,因此經過啟用函式後啟用值都相同),反向傳播過程中計算的梯度也是相同,每個權重引數的更新因此也是相同的,網路因此失去了不對稱性。

3.2用小的隨機數初始化

初始化引數應該非常接近於零(但不全等於零),來打破網路的對稱性。初始引數應該是隨機且獨立的來保證每個引數更新過程是不同的。給每個引數隨機賦予一個接近零的值:

W=0.01*numpy.Random.randn(D,H),randn方法生成一個零均值,方差為1的正態分佈的隨機數,同樣也可以換用數值較小的均勻分佈來產生初始化引數,但在實踐中兩種方法最終結果差別不大

3.3方差歸一化

用隨機初始化方法來初始化引數會導致輸出S的方差隨輸入數量(X或W向量的維度)增加而變大。

獨立隨機變數和的方差具有以下性質:Var(A+B+C)=Var(A)+ Var(B)+ Var(C)

S = w1*x1 + w2*x2 +…+wi*xi+ b   S是多個隨機變數的加權和,假設W各維度之間相互獨立,隨著資料維度增長,S的方差將會線性積累,由於資料的維度隨任務的不同,是不可控的,所以我們希望將S的方差做歸一化,這隻需要對W做處理就可以了:

W=numpy.random.randn(n)/sqrt(n)  #n是資料維度

上面操作是正確的推導過程:


令 n*Var(W) = 1,就得到std(W) = 1 / sqrt(n)。

注意:現在更多的論文中在實際中都在用ReLUs函式,針對ReLUs推薦:

w=numpy.random.randn(n)*sqrt(2.0/n)

4.訓練過程中

4.1卷積濾波器和池化層大小

輸入資料最好是2的整數冪次方,比如32(CIFAR-10中圖片尺寸),64,224(ImageNet中常見的尺寸)。此外採用較小尺寸的濾波器(例3x3),小的步長(例1)和0值填充,不僅會減少引數數量,還會提升整個網路的準確率。當用3x3的濾波器,步長為1,填充(pad)為1時,會保持圖片或特徵圖的空間尺寸不變。池化層經常用的池化大小是2x2.

4.2學習率

【2】中推薦 recommended to divide the gradients by mini-batch size.Thus, you should not always change the learning rates (LR), if you change themini batch size. 使用驗證集是獲得合適LR的有效手段。開始訓練時,LR通常設為0.1。在實踐中,當你觀察到在驗證集上的loss或者準確率不在變化時,將LR除以2或5後繼續跑。

4.3在預訓練的模型上微調

很多state-of-the-arts deep networks的模型被開源出來,這些預訓練的模型泛化能力(generalization abilities)很強,因此可以在這些模型的基礎上根據自己的任務微調。微調涉及兩個重要的因素:新資料集的大小和兩個資料集的相似度。網路頂層特徵包含更多dataset-specific特徵。

資料集相似性高

資料集相似性低

資料少

直接提取頂層特徵來訓練線性分類器

比較困難,嘗試用不同層的特徵訓練一個線性分類器。

資料多

用較小的學習率微調更多的層

用較小的學習率微調儘可能多的層

5.啟用函式

啟用函式用於在網路中引入非線性

sigmoid 與 tanh 曾經很流行,但現在很少用於視覺模型了,主要原因在於當輸入的絕對值較大時,其梯度(導數)接近於零,這時引數幾乎不再更新,梯度的反向傳播過程將被中斷,出現梯度消散的現象。


ReLU 優點:

實現起來非常簡單,加速了計算過程。

加速收斂,沒有飽和問題,大大緩解了梯度消散的現象。

ReLU 缺點:就是它可能會永遠“死”掉,假如有一組二維資料 X(x1, x2)分佈在 x1:[0,1],  x2:[0,1] 的區域內,有一組引數 W(w1, w2)對 X 做線性變換,並將結果輸入到ReLU。

F = w1*x1 + w2*x2

如果 w1 = w2 = -1,那麼無論 X 如何取值,F 必然小於等於零。那麼 ReLU 函式對 F 的導數將永遠為零。這個 ReLU 節點將永遠不參與整個模型的學習過程。

為了解決ReLU 在負區間的導數為零的問題,人們發明了 Leaky ReLU, Parametric ReLU,  Randomized ReLU 等變體,他們的中心思想都是為ReLU 函式在負區間賦予一定的斜率,從而讓其導數不為零(這裡設斜率為 alpha)。

 

Leaky ReLU 就是直接給 alpha 指定一個固定的值,整個模型都用這個斜率:

Parametric ReLU 將 alpha 作為一個引數,通過從資料中學習獲取它的最優值。

Randomized ReLU 的alpha 是在規定的區間內隨機選取的,在測試階段是定值。

有學者將當前最優的兩類CNN網路結合不同的啟用函式在CIFAR-10,CIFAR-100和NDSB資料集上做實驗,評價四種啟用函式的優劣。 實驗結果表明Leaky ReLU取較大的alpha準確率更好。Parametric ReLU很容易在小資料集上過擬合(訓練集上錯誤率最低,測試集上不理想),但依然比ReLU好。RReLU效果較好,實驗表明它可以克服模型過擬合,這可能由於alpha選擇的隨機性。在實踐中, Parametric ReLU 和 Randomized ReLU 都是可取的。

6.規則化(Regularizations)

7.從數字中觀察

7.1從學習率觀察。太高的學習率,loss曲線會很奇怪,很容易會出現引數爆炸現象;低學習率,loss下降很慢;高學習率,一開始loss會下降很快,但很容易跌入區域性最小值;好的學習率應該平滑下降。

7.2放大loss曲線觀察。圖2中橫座標是epoch(網路在整個訓練集上完整的跑一遍的時間,所以每個epoch中會有多個mini batches),縱座標是每個訓練batch的分類loss。如果loss曲線表現出線性(下降緩慢)表明學習率太低;如果loss不再下降,表明學習率太高陷入區域性最小值;曲線的寬度和batch size有關,如果寬度太寬,說明相鄰batch間的變化太大,應該減小batch size。

7.3從精確率曲線觀察。圖3中紅色線是訓練集上的精確率,綠色驗證集上的精確率。當驗證集上精確度收斂時,紅線和綠線間隔過大很明顯訓練集上出現了過擬合。當兩線間隔很小且準確率都很低時,說明模型學習能力太低,需要增加模型的capacity。

參考文獻