近年來,深度學習作為機器學習中比較火的一種方法出現在我們面前,但是和非深度學習的機器學習相比(我將深度學習歸于機器學習的領域內),還存在著幾點很大的不同,具體來說,有以下幾點:
1、深度學習,顧名思義,網絡變深了,這就意味著這種深度學習類的網絡可能有更多的layers,這意味著什么呢?也即表示這種深層的網絡需要學習更多的參數,盡管我們知道在CNN中有共享參數等等技巧,但在此前提下,不妨認為隨著網絡層數的增多,需要學習的參數也在增加,那問題又來了,參數增加有什么問題嗎?當然有問題,這是我們在機器學習領域內探討的最多的一個問題,因為我們的目的都是為了減少泛化誤差,提高模型的泛化能力,而在這一點,顯然深度學習比一般意義的機器學習模型要復雜,復雜的模型訓練不當,我們知道的,模型的泛化能力會顯著下降。
2、深度學習比一般意義的機器學習模型要復雜,不僅表現在上一點的模型本身(指的是layers和parameters),也表現在不同的工作原理上。深度學習不再需要人工設計指定的特征,分類的特征是模型自己去學到的,這一點上意味著深度學習需要有更多的data,這又是和一般意義上的機器學習有所區別的。舉個例子,同樣是識別車輛,Haar-like+Adaboost可能只需要2-3k訓練集,但對于深度學習來說,可能需要20-30k的數據集,當然這么多的data本身是和模型相匹配的,但是在一般意義上,不妨認為深度學習需要更多的data(本文不探討大數據和深度學習(人工智能)的關系,只在一般意義上做出說明)。
綜上所述,其實我們已經認識到了深度學習的本質,其實很簡單,就是數據和模型,兩者之間相輔相成,相互促進。認識到了深度學習的本質和與一般意義上的機器學習的區別,你才能明白調參和訓練的技巧和建議對于深度學習而言是多么的重要,毫不夸張的說,直接影響到我們剛剛談到的模型的泛化能力,而且是根本原因。
從我們準備數據集到訓練到理想的模型的過程順序,我們把其分成如下幾個部分分別敘述。
1、Data augmentation(數據增強)。
個人理解數據增強主要是在準備數據集時,由于需要的data較多又得不到滿足,則可以通過對顏色(color)、尺度(scale)、裁剪(crop)、翻轉(Flip)、添加噪聲(Noise)、旋轉(Rotation)等等,這樣就增加了數據集的數目,解決的是data不足的問題,近幾年GAN模型的研究也取得了較大的發展,其主要的出發點就是解決了監督學習data不足的問題,經??捎糜谔摂M場景的仿真等等,感興趣的可以深入研究。
2、Pre-processing(數據預處理)。
個人理解的是有了數據之后,難道就一定能很好的利用這些數據嗎?如何評價這些數據的好壞?那要對數據進行預處理,預處理的前提是要正確的理解數據。數據之間存在相關性嗎?假設你用了data augmentation,那顯然數據集之間的相關性是較大的,說直白點,你用了兩張一模一樣的數據在訓練集里,意義何在?所以接下來要講的數據預處理很重要。常用的方法有:normalization(歸一化)、PCA(主成分分析)、Whitening(白化)等。
(1)Normalization??梢赃@樣認為,歸一化主要在干這樣一件事:把數據從一個一般的分布,變成0均值、單位方差的分布,為什么這么干呢?原因是這么做更容易收斂,這種方法在Caffe框架中普遍使用(mean value或者mean binaryproto 文件)。Batch Normalization(BN)是一個升級版本,作者主要考慮當使用了飽和的激活函數時,例如sigmoid函數變成0均值、單位方差則會出現在該函數中間近似線性的那一段,這是非常糟糕的,中間線性的部分的擬合能力最差,因此降低了模型的表達capacity,所以BN應運而生,實驗表明,其效果sigmoid函數比Relu函數要好。
(2)PCA。研究如何以最少的信息丟失將眾多原有的變量信息濃縮到少數幾個維度上,即所謂的主成分。首先計算出協方差矩陣,然后求出協方差矩陣的特征向量,并用其對原特征進行線性變換,實現降維。
(3)Whitening。去除特征向量中各個特征之間的相關性,同時保證每個特征的方差一致。 設特征向量 X = (X1,X2,X3),對于向量 X,可以計算出相應的協方差矩陣(根據已有數據集來估計)。我們希望協方差矩陣是一個對角矩陣,因為這意味著 X 的每個元素之間都是互不關聯的,但是我們的數據并不具備這樣的性質。為了解耦數據,我們需要對原始特征向量執行一個變換,從而使得變換后的向量 Y 的各個特征之間相關性為0。設 Σ 是 X 的協方差矩陣,有:ΣΦ=ΦΛ, 那么 Λ 中的每個元素都是協方差矩陣的特征值,Φ 的每個列向量是相應的特征向量。如果對特征向量做變換:Y = XΦ = X(Φ1,Φ2,Φ3),此時根據向量 Y 計算出來的協方差矩陣是一個對角矩陣。對角矩陣 Λ 的特征值就是 Y 的每個元素的方差,可以全部相同,也可能不相同,如果對變換后的特征向量的某些維度進行縮放,使得 Λ 的每個元素都相等,那么整個過程就是 whitening。
3、Initialization(初始化)。
當前兩步完成之后,可以考慮模型參數的初始化方式了。此處舉出實例,Caffe中的參數初始化方式有7種方法,分別為:constant、gaussian、positive_unitball、uniform、xavier、msra和bilinear。用的較多的是xavier用在權重初始化上,constant用在偏置初始化上。
4、Activation Functions(激活函數)。
深度學習之所以具有豐富的表達能力,非常關鍵的一點是激活函數,這就相當于一系列疊加在一起的非線性處理單元,可以想象出這一系列疊加的非線性處理單元原則上可以逼近任意函數(這指的是從輸入到輸出效果)。幾種常用的激活函數:sigmoid、tanh和Relu,但是我們又介紹過之前廣泛使用的sigmoid和tanh等飽和激活函數,使用它們在很深網絡模型中的訓練效果往往很不好,因為存在梯度消失的問題,例如下圖中是一個sigmoid函數的例子,由于神經網絡在反向傳播時,需要乘以激活函數的一階導數,這樣逐層往前傳,可想0.930=0.042,這就產生了兩個極端,出現了如下圖所示的梯度消失區,一旦梯度都已經很小了,還怎么學習?我們在Caffe中常用Relu函數有效地避免這一問題。
圖1:sigmoid函數
5、During training(訓練過程中)。
在訓練過程中,要掌握學習率的變化策略,一般而言Caffe定義學習率在超參數配置文件中(solver.prototxt),并選擇了學習速率的衰減策略(學習速率都是開始的時候大,然后之后變小,如何變,怎么變,我們將其稱為策略,所以在論文中一般都會談到這一問題),更為重要的是,可以在網絡層定義中指定lr_mult選擇某一層的學習率,該技巧也可為之后的調參做準備。另外一點非常重要的是fine-tune,微調的用處通常情況下就是你選擇了一個較為深的model,也就是較為復雜的model,你并不需要把所有的layers都重新訓練,而只是訓練了其中的some layers,此時我們完全可以站在巨人的肩膀上(利用預訓練模型的weights初始化),可以省去很多工作,更為重要的是,加上合適的調參還會提高模型的泛化能力(因為預訓練的模型往往還未收斂)。
具體來說,存在以下幾種情形:
注意微調的時候,在Caffe中操作需要改變微調的那些層的名字(同時根據自己的需要改變layer參數,例如圖片的通道、全連接層輸出的類別數目等)。
6、Regularizations(正則化)。
正則化也稱為Weight-decay(限制權值)。正則化應該講是一種避免over-fitting的有效方法,這里我們插入一段對over-fitting的分析,就我的認識而言,從事機器學習的工程師們經常會遇到很多問題,很多bug,但是可以這樣說over-fitting是所有工程師都必須面對的一個問題,其具有很強的通用性,這是由于方法本身所決定的。既然大家都會遇到這個問題,又該如何解決呢?回頭看,我們說過深度學習的本質就是數據和模型,那解決過擬合的根本途徑也必須從這兩個方向出發,那什么是過擬合呢?形象一點說就是你認為你的model在訓練集上已經表現很好了,可是當你把它使用在驗證集上的時候,效果則很差,進一步說就是數據集太少或者模型太復雜,兩者顯然不匹配?,F在我們開始從這兩個方向分析,解決方法兩個:增加數據集和減小模型的復雜度(限制網絡的capacity)。此處正則化就是從減小模型的復雜度出發的一項技術,其本質就是控制模型學習的特征數目,使其最小化,從而防止在訓練過程中引入訓練集的抽樣誤差,正則化包括L2正則化和L1正則化。
7、Dropout。
Dropout是指在深度學習網絡的訓練過程中,對于神經網絡單元,按照一定的概率將其暫時從網絡中丟棄,如下圖所示。對于隨機梯度下降來說,由于是隨機丟棄,因此每一個mini-batch都在訓練不同的網絡(對于一個有N個節點的神經網絡,采用dropout后,可以認為其是2n個模型的集合),同時每個網絡只見過一個訓練數據(每次都是隨機的新網絡),從而將這些多個模型組合起來,以每個模型的平均輸出作為結果,caffe中也定義了Dropout層。
圖2 Dropout示例
8、Insights from Figures。
如果說通過上面的方法,你都做了,還是存在問題,那就需要仔細的檢查了,檢查的方法有很多,其中最為形象生動的,也就是這里要說的就是畫圖,從圖中進行推斷。我們知道Caffe也給我們提供了很多畫圖的tools(稱其為可視化),這對寫論文、科研分析還是挺好的。言歸正傳,下面從網上找到幾張圖片,這些圖片都可以從log中通過tools畫出,讓我們來看一看。
圖3表示的是不同學習率下的loss變化曲線,很明顯圖中的四條曲線隨著迭代次數的增加表現出不同的性能,黃色的曲線隨著迭代次數的增加,loss先減少而后劇烈增加,往往引發loss等于Nan,這是由于選擇的學習率太大的緣故(ps:本人親測,有幾次我在修改一些模型時,開始的loss就很大,然后選擇了較大的學習率,一下子就Nan了);藍色的曲線隨著迭代次數的增加,loss的減少速率很慢很慢,而且設置的最大迭代次數已經很大,但網絡并沒有收斂,這說明選擇的學習率太小了;綠色的曲線隨著迭代次數的增加,loss的很快減少,并且網絡收斂在一個loss較高的地方居高不下,這說明選擇的學習率有點大了,已達到局部最優,可觀察在網絡loss不降時降低學習率;紅色的曲線隨著迭代的次數的增加,loss緩慢下降,曲線相對平滑,最終收斂在loss很低的水平上,說明選擇的學習率較好。當然圖中是理想的曲線,只能說明變化趨勢,實際情況下曲線是有波動的,有些毛刺感(ps:大量的實踐證明可以接受的就是局部最優和全局最優了,也就是紅色和綠色曲線代表的過程,當然大多數同志們遇到的都是局部最優,此時我們考慮在局部最優的基礎上減小學習率繼續訓練,兩者的區別就是局部最優會保持在一個較高的loss上,當然怎么衡量loss高低沒有標準,所以局部最優不代表訓練結果就差,局部最優的結果也可以媲美全局最優,因為我們根本不知道全局最優在哪個地方)。
圖3:學習率與loss的關系曲線
圖4表示的是不同迭代次數的loss變化曲線,從圖中可以看到隨著迭代次數的增加,loss的變化趨勢是減小的,注意圖中標注出的“寬度”,如果曲線的寬度太大了,則說明有可能你選擇的batch太小了,而其實batch的選擇在深度學習中也不是隨便來的,太大了不好,太小了也不好,太大了會有顯存溢出的錯誤,太小了有可能某個label很難被學到,這往往導致模型不收斂,或者出現loss為Nan等錯誤。這個時候可以用accum_batch_size來解決由于硬件不足不能選擇較大batch的問題。
圖4:迭代次數與loss的關系曲線
圖5是模型在訓練集和驗證集上的精度曲線。紅色曲線表示的是模型在訓練集上的分類精度,可以看到,還不錯,隨著迭代次數增加,分類的精度也在增加,并且有收斂的趨勢;綠色曲線表示的是模型在驗證集上的分類精度,可以看出,與訓練集的精度相比,差距很大,說明模型over-fitting了,應該運用上面說到過的解決方法解決。如果圖中兩者之間沒什么大的差距而且精度都很低,應該增加模型的capacity,提升性能。
圖5:模型在訓練集和驗證集上的精度曲線
我們都在通往真理的路上。
評論
查看更多