機器學習模型在訓練數據集和測試數據集上的表現。若是你改變過實驗中的模型結構或者超參數,你也許發現了:當模型在訓練數據集上更準確時,它在測試數據集上卻不⼀定更準確。這是爲何呢?git
由於存在着訓練偏差和泛化偏差:github
訓練偏差的指望小於或等於泛化偏差。也就是說,⼀般狀況下,由訓練數據集學到的模型參數會使模型在訓練數據集上的表現優於或等於在測試數據集上的表現。因爲⽆法從訓練偏差估計泛化偏差,⼀味地下降訓練偏差並不意味着泛化偏差⼀定會下降。面試
機器學習模型應關注下降泛化偏差。算法
在機器學習中,一般須要評估若⼲候選模型的表現並從中選擇模型。這⼀過程稱爲模型選擇(model selection)。可供選擇的候選模型能夠是有着不一樣超參數的同類模型。以多層感知機爲例,咱們能夠選擇隱藏層的個數,以及每一個隱藏層中隱藏單元個數和激活函數。爲了獲得有效的模型,咱們一般要在模型選擇上下⼀番功夫。網絡
從嚴格意義上講,測試集只能在全部超參數和模型參數選定後使⽤⼀次。不可使⽤測試數據選擇模型,如調參。因爲⽆法從訓練偏差估計泛化偏差,所以也不該只依賴訓練數據選擇模型。鑑於此,咱們能夠預留⼀部分在訓練數據集和測試數據集之外的數據來進⾏模型選擇。這部分數據被稱爲驗證數據集,簡稱驗證集(validation set)。例如,咱們能夠從給定的訓練集中隨機選取⼀小部分做爲驗證集,而將剩餘部分做爲真正的訓練集。機器學習
能夠經過預留這樣的驗證集來進行模型選擇,判斷驗證集在模型中的表現能力。函數
因爲驗證數據集不參與模型訓練,當訓練數據不夠⽤時,預留⼤量的驗證數據顯得太奢侈。⼀種改善的⽅法是K折交叉驗證(K-fold cross-validation)。在K折交叉驗證中,咱們把原始訓練數據集分割成K個不重合的⼦數據集,而後咱們作K次模型訓練和驗證。每⼀次,咱們使⽤⼀個⼦數據集驗證模型,並使⽤其餘K − 1個⼦數據集來訓練模型。在這K次訓練和驗證中,每次⽤來驗證模型的⼦數據集都不一樣。最後,咱們對這K次訓練偏差和驗證偏差分別求平均。性能
給定訓練數據集,學習
應對⽋擬合和過擬合的⼀個辦法是針對數據集選擇合適複雜度的模型。測試
訓練數據集⼤⼩
影響⽋擬合和過擬合的另⼀個重要因素是訓練數據集的⼤小。⼀般來講,若是訓練數據集中樣本數過少,特別是⽐模型參數數量(按元素計)更少時,過擬合更容易發⽣。此外,泛化偏差不會隨訓練數據集⾥樣本數量增長而增⼤。所以,在計算資源容許的範圍以內,咱們一般但願訓練數據集⼤⼀些,特別是在模型複雜度較⾼時,例如層數較多的深度學習模型。
正則化
應對過擬合問題的常⽤⽅法:權重衰減(weight decay),權重衰減等價於L2範數正則化(regularization)。正則化經過爲模型損失函數添加懲罰項使學出的模型參數值較小,是應對過擬合的常⽤⼿段。
除了上面提到的權重衰減之外,深度學習模型經常使⽤丟棄法(dropout)來應對過擬合問題。丟棄法有⼀些不一樣的變體。本節中提到的丟棄法特指倒置丟棄法(inverted dropout)。
回憶⼀下,「多層感知機」描述了⼀個單隱藏層的多層感知機。其中輸⼊個數爲4,隱藏單元個數爲5,且隱藏單元hi(i = 1, . . . , 5)的計算表達式爲:
這⾥ϕ是激活函數,x1, . . . , x4是輸⼊,隱藏單元i的權重參數爲w1i, . . . , w4i,誤差參數爲bi。當對該隱藏層使⽤丟棄法時,該層的隱藏單元將有⼀定機率被丟棄掉。設丟棄機率爲p,那麼有p的機率hi會被清零,有1 − p的機率hi會除以1 − p作拉伸。丟棄機率是丟棄法的超參數。具體來講,設隨機變量ξi爲0和1的機率分別爲p和1 − p。使⽤丟棄法時咱們計算新的隱藏單元 。
因爲E(ξi) = 1 − p,所以:
**即丟棄法不改變其輸⼊的指望值。**讓咱們對隱藏層使⽤丟棄法,⼀種可能的結果以下圖所⽰,其中h2和h5被清零。這時輸出值的計算再也不依賴h2和h5,在反向傳播時,與這兩個隱藏單元相關的權重的梯度均爲0。因爲在訓練中隱藏層神經元的丟棄是隨機的,即h1, . . . , h5都有可能被清零,輸出層的計算⽆法過分依賴h1, . . . , h5中的任⼀個,從而在訓練模型時起到正則化的做⽤,並能夠⽤來應對過擬合。在測試模型時,咱們爲了拿到更加肯定性的結果,⼀般不使⽤丟棄法。
訓練神經網絡,尤爲是深度神經所面臨的一個問題就是梯度消失或梯度爆炸,也就是你訓練神經網絡的時候,導數或坡度有時會變得很是大,或者很是小,甚至於以指數方式變小,這加大了訓練的難度。
本質上,梯度消失和爆炸是一種狀況。在深層網絡中,因爲網絡過深,若是初始獲得的梯度太小,或者傳播途中在某一層上太小,則在以後的層上獲得的梯度會愈來愈小,即產生了梯度消失。梯度爆炸也是一樣的。通常地,不合理的初始化以及激活函數,如sigmoid等,都會致使梯度過大或者太小,從而引發消失/爆炸。
解決方案
預訓練加微調
其基本思想是每次訓練一層隱節點,訓練時將上一層隱節點的輸出做爲輸入,而本層隱節點的輸出做爲下一層隱節點的輸入,此過程就是逐層「預訓練」(pre-training);在預訓練完成後,再對整個網絡進行「微調」(fine-tunning)。
此方法有必定的好處,可是目前應用的不是不少了。
梯度剪切、正則
梯度剪切這個方案主要是針對梯度爆炸提出的,其思想是設置一個梯度剪切閾值,而後更新梯度的時候,若是梯度超過這個閾值,那麼就將其強制限制在這個範圍以內。這能夠防止梯度爆炸。
另一種解決梯度爆炸的手段是採用權重正則化(weithts regularization)比較常見的是L1和L2正則。
ReLu、leakReLu等激活函數
ReLu:其函數的導數在正數部分是恆等於1,這樣在深層網絡中,在激活函數部分就不存在致使梯度過大或者太小的問題,緩解了梯度消失或者爆炸。同時也方便計算。固然,其也存在存在一些缺點,例如過濾到了負數部分,致使部分信息的丟失,輸出的數據分佈不在以0爲中心,改變了數據分佈。
leakrelu:就是爲了解決relu的0區間帶來的影響,其數學表達爲:leakrelu=max(k*x,0)其中k是leak係數,通常選擇0.01或者0.02,或者經過學習而來。
Batch Normalization
Batch Normalization是深度學習發展以來提出的最重要的成果之一了,目前已經被普遍的應用到了各大網絡中,具備加速網絡收斂速度,提高訓練穩定性的效果,Batch Normalization本質上是解決反向傳播過程當中的梯度問題。Batch Normalization,簡稱BN,即批規範化,經過規範化操做將輸出信號x規範化到均值爲0,方差爲1保證網絡的穩定性。
殘差結構
殘差的方式,能使得深層的網絡梯度經過跳級鏈接路徑直接返回到淺層部分,使得網絡不管多深都能將梯度進行有效的回傳。
LSTM
LSTM全稱是長短時間記憶網絡(long-short term memory networks),是不那麼容易發生梯度消失的,主要緣由在於LSTM內部複雜的「門」(gates)。在計算時,將過程當中的梯度進行了抵消。
你能夠把訓練集分割爲小一點的子集訓練,這些子集被取名爲 mini-batch,假設每個子集中只有 1000 個樣本,那麼把其中的𝑥 (1)到𝑥 (1000)取出來,將其稱爲第一個子訓練集,也叫作 mini-batch,而後你再取出接下來的 1000 個樣本,從𝑥 (1001)到𝑥 (2000),而後再取 1000個樣本,以此類推。
在訓練集上運行 mini-batch 梯度降低法,你運行 for t=1……5000,由於咱們有5000個各有 1000 個樣本的組,在 for 循環裏你要作得基本就是對𝑋 {𝑡}和𝑌 {𝑡}執行一步梯度降低法。
其中1<n<m,m表示整個訓練集大小。
優缺點:
首先,若是訓練集較小,直接使用 batch 梯度降低法,這裏的少是說小於 2000 個樣本。通常的 mini-batch 大小爲 64 到 512,考慮到電腦內存設置和使用的方式,若是 mini-batch 大小是 2 的𝑛次方,代碼會運行地快一些。
在每次迭代中,梯度降低根據⾃變量當前位置,沿着當前位置的梯度更新⾃變量。然而,若是⾃變量的 迭代⽅向僅僅取決於⾃變量當前位置,這可能會帶來⼀些問題。
讓咱們考慮⼀個輸⼊和輸出分別爲⼆維向量x = [x1, x2]⊤和標量的⽬標函數 。,這⾥將係數從1減少到了0.1。下⾯實現基於這個⽬標函數的梯度降低,並演⽰使⽤學習率爲0.4時⾃變量的迭代軌跡。
能夠看到,同⼀位置上,⽬標函數在豎直⽅向(x2軸⽅向)⽐在⽔平⽅向(x1軸⽅向)的斜率的絕對值更⼤。**所以,給定學習率,梯度降低迭代⾃變量時會使⾃變量在豎直⽅向⽐在⽔平⽅向移動幅度更⼤。**那麼,咱們須要⼀個較小的學習率從而避免⾃變量在豎直⽅向上越過⽬標函數最優解。然而,這會形成⾃變量在⽔平⽅向上朝最優解移動變慢。
**動量法的提出是爲了解決梯度降低的上述問題。**因爲小批量隨機梯度降低⽐梯度降低更爲⼴義,本章後續討論將沿⽤「小批量隨機梯度降低」⼀節中時間步t的小批量隨機梯度gt的定義。設時間步t的⾃變量爲xt,學習率爲ηt。在時間步0,動量法建立速度變量v0,並將其元素初始化成0。在時間步t > 0,動量法對每次迭代的步驟作以下修改:
其中,動量超參數γ滿⾜0 ≤ γ < 1。當γ = 0時,動量法等價於小批量隨機梯度降低。在梯度降低時候使用動量法後的迭代軌跡:
能夠看到使⽤較小的學習率η = 0.4和動量超參數γ = 0.5時,動量法在豎直⽅向上的移動更加平滑,且在⽔平⽅向上更快逼近最優解。
因此,在動量法中,⾃變量在各個⽅向上的移動幅度不只取決當前梯度,還取決於過去的各個梯度在各個⽅向上是否⼀致。在本節以前⽰例的優化問題中,全部梯度在⽔平⽅向上爲正(向右),而在豎直⽅向上時正(向上)時負(向下)。這樣,咱們就可使⽤較⼤的學習率,從而使⾃變量向最優解更快移動。
優化算法中,⽬標函數⾃變量的每⼀個元素在相同時間步都使⽤同⼀個學習率來⾃我迭代。在「動量法」⾥咱們看到當x1和x2的梯度值有較⼤差異時,須要選擇⾜夠小的學習率使得⾃變量在梯度值較⼤的維度上不發散。但這樣會致使⾃變量在梯度值較小的維度上迭代過慢。動量法依賴指數加權移動平均使得⾃變量的更新⽅向更加⼀致,從而下降發散的可能。本節咱們介紹AdaGrad算法,它根據⾃變量在每一個維度的梯度值的⼤小來調整各個維度上的學習率,從而避免統⼀的學習率難以適應全部維度的問題。
AdaGrad算法會使⽤⼀個小批量隨機梯度gt按元素平⽅的累加變量st。在時間步0,AdaGrad將s0中每一個元素初始化爲0。在時間步t,⾸先將小批量隨機梯度gt按元素平⽅後累加到變量st:
其中⊙是按元素相乘。接着,咱們將⽬標函數⾃變量中每一個元素的學習率經過按元素運算從新調整⼀下:
其中η是學習率,ϵ是爲了維持數值穩定性而添加的常數,如10的-6次方。這⾥開⽅、除法和乘法的運算都是按元素運算的。這些按元素運算使得⽬標函數⾃變量中每一個元素都分別擁有⾃⼰的學習率。
須要強調的是,小批量隨機梯度按元素平⽅的累加變量st出如今學習率的分⺟項中。所以,
然而,因爲st⼀直在累加按元素平⽅的梯度,⾃變量中每一個元素的學習率在迭代過程當中⼀直在下降(或不變)。因此,當學習率在迭代早期降得較快且當前解依然不佳時,AdaGrad算法在迭代後期因爲學習率太小,可能較難找到⼀個有⽤的解。
當學習率在迭代早期降得較快且當前解依然不佳時,AdaGrad算法在迭代後期因爲學習率太小,可能較難找到⼀個有⽤的解。爲了解決這⼀問題,RMSProp算法對AdaGrad算法作了⼀點小小的修改。
不一樣於AdaGrad算法⾥狀態變量st是截⾄時間步t全部小批量隨機梯度gt按元素平⽅和,RMSProp算法將這些梯度按元素平⽅作指數加權移動平均。具體來講,給定超參數0 ≤ γ < 1,RMSProp算法在時間步t > 0計算:
和AdaGrad算法⼀樣,RMSProp算法將⽬標函數⾃變量中每一個元素的學習率經過按元素運算從新調整,而後更新⾃變量:
其中η是學習率,ϵ是爲了維持數值穩定性而添加的常數,如10的-6次方。由於RMSProp算法的狀態變量st是對平⽅項gt ⊙ gt的指數加權移動平均,因此能夠看做是最近1/(1 − γ)個時間步的小批量隨機梯度平⽅項的加權平均。如此⼀來,⾃變量每一個元素的學習率在迭代過程當中就再也不⼀直下降(或不變)。
除了RMSProp算法之外,另⼀個常⽤優化算法AdaDelta算法也針對AdaGrad算法在迭代後期可能較難找到有⽤解的問題作了改進。有意思的是,AdaDelta算法沒有學習率這⼀超參數。
AdaDelta算法也像RMSProp算法⼀樣,使⽤了小批量隨機梯度gt按元素平⽅的指數加權移動平均變量st。在時間步0,它的全部元素被初始化爲0。給定超參數0 ≤ ρ < 1(對應RMSProp算法中的γ),在時間步t > 0,同RMSProp算法⼀樣計算:
與RMSProp算法不一樣的是,AdaDelta算法還維護⼀個額外的狀態變量∆xt,其元素一樣在時間步0時被初始化爲0。咱們使⽤∆xt−1來計算⾃變量的變化量:
最後,咱們使⽤∆xt來記錄⾃變量變化量 按元素平⽅的指數加權移動平均:
能夠看到,如不考慮ϵ的影響,AdaDelta算法與RMSProp算法的不一樣之處在於使⽤ 來替代超參數η。
Adam算法在RMSProp算法基礎上對小批量隨機梯度也作了指數加權移動平均。
Adam算法使⽤了動量變量vt和RMSProp算法中小批量隨機梯度按元素平⽅的指數加權移動平均變量st,並在時間步0將它們中每一個元素初始化爲0。給定超參數0 ≤ β1 < 1(算法做者建議設爲0.9),時間步t的動量變量vt即小批量隨機梯度gt的指數加權移動平均:
和RMSProp算法中⼀樣,給定超參數0 ≤ β2 < 1(算法做者建議設爲0.999),將小批量隨機梯度按元素平⽅後的項gt ⊙ gt作指數加權移動平均獲得st:
因爲咱們將 v0 和 s0 中的元素都初始化爲 0,在時間步 t 咱們獲得 。將過去各時間步小批量隨機梯度的權值相加,獲得 。須要注意的是,當 t 較小時,過去各時間步小批量隨機梯度權值之和會較小。例如,當β1 = 0.9時,v1 = 0.1g1。爲了消除這樣的影響,對於任意時間步 t,咱們能夠將 vt 再除以 ,從而使過去各時間步小批量隨機梯度權值之和爲1。這也叫做誤差修正。在Adam算法中,咱們對變量 vt 和 st 均做誤差修正:
接下來,Adam算法使⽤以上誤差修正後的變量***v*ˆt和***s*ˆt,將模型參數中每一個元素的學習率經過按元素運算從新調整:
其中η是學習率,ϵ是爲了維持數值穩定性而添加的常數,如10的-8次方。和AdaGrad算法、RMSProp算法以及AdaDelta算法⼀樣,⽬標函數⾃變量中每一個元素都分別擁有⾃⼰的學習率。最後,使⽤ 迭代⾃變量:
一個具備高維度空間的函數,若是梯度爲 0,那麼在每一個方向,它多是凸函數,也多是凹函數。若是你在 2 萬維空間中,那麼想要獲得局部最優,全部的 2 萬個方向都須要是這樣,但發生的機率也許很小,也許是2的-20000次方,你更有可能遇到有些方向的曲線會這樣向上彎曲,另外一些方向曲線向下彎,而不是全部的都向上彎曲,所以在高維度空間,你更可能碰到鞍點。
而不會碰到局部最優。**至於爲何會把一個曲面叫作鞍點,**你想象一下,就像是放在馬背上的馬鞍同樣,若是這是馬,這是馬的頭,這就是馬的眼睛,畫得很差請多包涵,而後你就是騎馬的人,要坐在馬鞍上,所以這裏的這個點,導數爲 0 的點,這個點叫作鞍點。我想那確實是你坐在馬鞍上的那個點,而這裏導數爲 0。
鞍點中的平穩段是一個問題,這樣使得學習十分緩慢,**這也是像 Momentum 或是RMSprop,Adam 這樣的算法,可以加速學習算法的地方。**在這些狀況下,更成熟的優化算法,如 Adam 算法,可以加快速度,讓你儘早往下走出平穩段。
**數據角度 **
加強數據集。不管是有監督仍是無監督學習,數據永遠是最重要的驅動力。更多的類型數據對良好的模型能帶來更好的穩定性和對未知數據的可預見性。對模型來講,「看到過的總比沒看到的更具備判別的信心」。
模型角度
模型的容限能力決定着模型可優化的空間。在數據量充足的前提下,對同類型的模型,增大模型規模來提高容限無疑是最直接和有效的手段。
調參優化角度
若是你知道模型的性能爲何再也不提升了,那已經向提高性能跨出了一大步。 超參數調整自己是一個比較大的問題。通常能夠包含模型初始化的配置,優化算法的選取、學習率的策略以及如何配置正則和損失函數等等。
訓練角度
在越大規模的數據集或者模型上,誠然一個好的優化算法總能加速收斂。但你在未探索到模型的上限以前,永遠不知道訓練多久算訓練完成。因此在改善模型上充分訓練永遠是最必要的過程。充分訓練的含義不只僅只是增大訓練輪數。有效的學習率衰減和正則一樣是充分訓練中很是必要的手段。
做者:@mantchs
GitHub:github.com/NLP-LOVE/ML…