在這節課中,主要講述了神經網絡的檢查事項(例如梯度檢查,合理性檢查和學習過程中對損失函數、權重、每層的激活函數與梯度分布等的檢查等)和神經網絡的參數調優實現方法(例如:隨機梯度下降方法,動量方法,學習率退火方法等等) -----------第一部分:檢查事項---------- 梯度檢查:課中提出當使用有限差值來近似計算數值梯度的時候,下面的公式方法是不可行的:
而在實際中常使用下面的中心化梯度計算公式:
公式2的結果要比公式1更準確,公式1的誤差近似為O(h),第二個公式的誤差近似為O(h^2),
另外,在進行誤差比較時,應該使用下面的相對誤差比較法:
公式3比較誤差時是計算的兩者的差值占兩個梯度絕對值較大值(分母取的是兩個梯度絕對值的最大值)的比例,分母也可以是兩個梯度絕對值的和。這樣做可以防止當其中一個梯度等于0時,分母為0的情況(這種情況在ReLU中經常發生),所以還需要注意當兩個梯度都為零時并且通過了梯度檢查的情況。老師給出了在實踐中的幾種情形:
在多層神經網絡中,誤差時逐層累積的。對于一個可微分函數,如果誤差為1e-2,通常就是梯度計算出錯了。 另外,梯度檢查時所用的數值精度也會影響到結果,例如,可能出現使用單精度數的相對誤差為1e-2,但使用雙精度數時的相對誤差為1e-8的情況。 還需要注意保持浮點數的有效范圍,在論文《What Every Computer Scientist Should Konw About Floating-Point Artthmetic》描述了多種可能因為浮點數值計算導致的錯誤。老師建議將原始的解析梯度和數值梯度數據打印出來,以確保用來比較的數值不要太小(通常絕對值小于1e-10是很壞的情況)。但是如果出現確實過小的情形,可以借助一個常數將損失函數的數值范圍暫時擴展到一個更“好”的范圍,使得浮點數變得更加密集;比較理想的數值范圍是在1.0的數量級上,即浮點數指數為0。 還有一種情況是:目標函數存在不可導點(kinks)。 不可導點是指目標函數不存在導數的部分,ReLU、SVM損失函數、Maxout神經元等都存在kinks點。以ReLU函數為例,當x=0時,函數不可導,即是函數的一個kinks點,下圖1是ReLU的函數曲線:
在x=e-6處,理論梯度應該是0,但當使用上面公式(2)求梯度時,如果h>e-6,求出的梯度結果并不為0,因為 f(x+h) 越過了不可導點。而在實際應用中,上述情況是很常見。例如,用CIFAR-10訓練的SVM中,樣本數為50000個,每個樣本產生9個 max(0,x) 式子,所以共有 450,000個式子,所以遇到很多的不可導點是正常現象。 針對上面的情形,課中給出的建議是: (1)使用少量的數據點。因為含有不可導點損失函數的數據點越少,出現的不可導點就越少,在計算有限差值近似時越過不可導點的概率就越小;并且這還可以使得檢查過程變得高效。 (2)謹慎設置步長 h 。步長值并不是越小越好,當h過小時,可能會遇到上面說的數值精度問題。如果梯度檢查無法進行,可以嘗試將 h 調到1e-4或者1e-6。 (3)需要注意梯度檢查的時機。最好讓神經網絡學習一小段時間,等到損失函數開始下降的以后再進行梯度檢查。因為如果從一開始就進行梯度檢查,此時梯度可能正處于不正常的邊界。 另外,梯度檢查還需要注意的三點有: (1)計算數據損失時注意正則化損失的影響,不要讓正則化損失掩蓋數據損失。 由于損失函數包括數據損失和正則化損失兩部分,所以可能存在正則化損失吞沒數據損失的風險。建議做法是:先關掉正則化部分,而是對數據損失做單獨檢查,然后再對正則化損失做單獨檢查。 對正則化做單獨檢查的方法有:1. 修改代碼,去掉其中數據損失的部分; 2.提高正則化強度,確認其效果在梯度檢查中能否忽略。 (2)注意隨機失活和數據擴張的不確定影響。 這可能給計算梯度結果帶來不確定的誤差影響。如果關閉這些操作,則無法對它們進行梯度檢查(例如隨機失活的反向傳播可能存在錯誤),所以更好的解決方法是在計算 f(x+h) 和 f(x-h) 前強制增加一個特定的隨機種子,在計算解析梯度時也采取這個方法。 (3)檢查少量的維度。 在實際應用中,神經網絡可能有上百萬的參數,在這種情況下只能檢查部分維度。但需要注意的是,選取的參數應該從所有不同的參數中選取部分檢查,避免出現從參數向量中隨機選取出的參數可能只是偏置參數的情況。 進行學習之前的合理性檢查技巧:
參數調優的過程是費時費力的,所以在開始之前,下面的技巧是很有必要的: (1)原文中“Look for correct loss at chance performance”,這里的chance performance指的是不是統計概率中的得分的意思(我不確定,如果有清楚的還望告知!)。 當使用小參數初始化時,確保得到的損失值與期望的損失值是一樣的。最好的方式是單獨對數據損失進行檢查(正則化強度置零)。 (2)當增大正則化強度時,查看損失值是否跟著變大。 (3)在整個數據集進行訓練之前,先在一個很小的數據集上進行訓練(比如20個數據),并設置正則化強度為0,確保此時的損失值為0。只有這個檢查通過,整個數據集的訓練才有意義。 學習過程中的檢查:
在神經網絡訓練過程中,有許多有用的參數(例如損失函數值,驗證集和訓練集的準確率,權重的更新比例等)需要監控,這些參數對于不同超參數的設置和調優具有指導意義。 (1)損失函數值
上圖2中,x軸表示周期。左面是不同學習率對應的損失函數值曲線;右圖是一個典型的損失函數值隨時間的變化曲線。從左圖中,我們發現,學習率設置過高時,損失值并不單調了,而紅色曲線對應的是較好的學習率。 另外,損失函數值的震蕩程度還與批尺寸(batch size)有關:當批尺寸為1時,震蕩相對會比較大;當批尺寸是整個數據集時,震蕩會比較小,因為每個梯度的更新都在單調地優化損失函數(學習率過高除外)。 (2)訓練集和驗證集的準確率
上圖3中,藍色的驗證集曲線表明相比于訓練集/驗證集的準確率低了很多,兩者中間的縫隙程度也能模型過擬合的程度。此時應該增大正則化強度(更大的權重懲罰,更多的隨機失活等)或者收集更多的數據。 如果遇到驗證集曲線和訓練集曲線近乎重合的情況,說明模型容量不夠大,此時應該通過增加參數的數量使得模型容量更大些。
(3)權重的更新比例
這個之前課中也提過,這個參數指的是每次訓練后有更新的權重占所有權重的比例。經驗性的結論是這個比例應該在1e-3左右,如果小于此值,表明學習率可能設置的過小;如果大于此值,表明學習率可能設置的過大。
(4)課中還給出了幾種判別學習過程是否出現問題的方法
上圖是將將神經網絡的第一層權重可視化的例子。左邊的特征充滿了噪音,表明網絡可能出現了以下問題:網絡不收斂,學習率設置不恰當,正則化懲罰的權重過低等。右邊的特征比較平滑,干凈而且種類多,表明訓練過程良好。
-----------第二部分:參數調優----------
參數更新:
優化算法是通過改善訓練方式,來最小化(或最大化)損失函數的過程。優化算法分為兩大類: 2. 二階優化算法。 二階優化算法使用二階導數(也叫Hessian方法)優化損失函數。課中也提及了其迭代公式,但是由于其計算成本比較高,所以應用的并不廣泛,不加說明了。
當可以使用反向傳播計算解析梯度后,梯度能被用來進行更新參數的過程。課中提及了幾種網絡優化算法:梯度下降法,動量更新法,學習率退火法等。 (1)梯度下降法。 參數更新最簡單的方式是沿著梯度負方向改變參數。假設參數向量為x ,其梯度為dx,更新形式為:
其中,learning_rate是之前說的學習率。注:批量梯度下降在計算損失函數的梯度時,是遍歷數據集中的每一個樣本,如果在每一次迭代中都進行梯度下降是非常低效的,因為算法的每次迭代僅以很小的步進來提升損失函數。為了解決這個問題,可以使用小批量(Mini-batch)梯度下降算法,該算法在數據集的一個小批量上近似計算梯度,然后使用這個梯度去更新權值。比如卷積神經網絡,每次在訓練集中選擇包含256個樣本的一批數據,然后使用這批數據計算梯度,完成參數更新,代碼附在下面。用來估計梯度的 batch 大小是可以選擇的一個超參數,當它等于 1 時,即為隨機梯度下降(SGD),大多數深度學習框架都會選擇隨機梯度下降的 batch 大小。
使用梯度下降的挑戰:1. 很難選擇合適的學習率。學習率太小會導致網絡收斂過于緩慢,而學習率太大可能會影響收斂,并導致損失函數在最小值上波動,甚至出現梯度發散。 2. 相同的學習率并不適用于所有的參數更新。尤其是訓練集數據很稀疏,并且特征頻率非常不同的時候;對于很少出現的特征,應使用更大的更新率。 3. 在神經網絡中,最小化非凸誤差函數的一大挑戰是避免陷于局部最小值中。實際問題中這并非源于局部極小值,而是來自鞍點,即在一個維度向上傾斜但在另一維度向下傾斜的點。鞍點通常被相同誤差值的平面包圍,這使得SGD算法很難脫離出來,因為梯度在所有維度上接近于零。 (2)動量更新法。動量法或說具有動量的 SGD 有助于加速向量向著正確的梯度方向下降,加快收斂速度。
SGD方法中的高方差振蕩會使得網絡震蕩,動量(Momentum)更新方法可以通過優化相關方向的訓練和弱化無關方向的振蕩,來加速SGD訓練過程。動量更新有兩種定義方法:一種是吳恩達提出的:定義一個動量,即是梯度的移動平均值。然后用它來更新網絡的權重,公式如下:
式中 L 是損失函數,α 是學習率,β為動量項,一般取值0.9。另一種表達動量更新的方式是:
Nesterov動量:當參數向量位于位置 x 時,由上面的代碼可知,動量部分會通過 mu * v 稍微改變參數向量。可以將未來的近似位置x + mu * v 看做是“向前看”,并計算 x + mu * v處的梯度。視圖如下:
(3)學習率退火算法
訓練深度網絡過程中,讓學習率隨著時間減弱是一種有效地方法。如果學習率很高,系統的動能就很大,參數向量跳動的就回厲害,不能夠穩定到損失函數更深更窄的區域。通常,學習率退火有3種方式:
單參數自適應學習率方法前面方法中的學習率是一種全局操作,并且對所有的參數都是使用同樣的學習率。學習率調參是很耗費資源的過程,下面是幾種自適應學習率調參的方法。
(1)Adagrad 是由Duchi等提出的自適應學習率算法。
其中,變量 cache 的尺寸和梯度矩陣的尺寸是相同的,它跟蹤每個參數的梯度平方和。由于,cache 放在分母位置,所以在更新參數 x 時,高梯度值的權重的學習率會被減弱,而低梯度值的權重的學習率會被增強。eps 用于平滑(一般設為1e-4到1e-8),可以防止出現除數為0的情況。Adagrad的缺點是,在深度學習中單調的學習率通常過于激進并且過早地停止學習。(2)RMSprop,該方法并未發表,出自于Geoff Hinton的Coursera課程中的第六節課的第29頁PPT。該方法是對Adagrad方法的改進,它使用梯度平方的滑動平均方式使得不像Adagrad那樣激進。 其中,decay_rate 是一個超參數,常用的值為[0.9,0.99,0.999]中的一個。與 Adagrad不同的是,學習率不會單調變小。(3)Adam,Adam看起來像是RMSProp的動量版。
在引述論文中,推薦的參數值為:eps=1e-8, beta1=0.9, beta2=0.999。由于 m,v 兩個矩陣初始為0,所以完整的Adam算法還包含了偏置(bias)的矯正方法。一般,Adam比RMSProp要好,老師推薦的更新方法是SGD+Nesterov動量方法,或Adam方法。![]() ![]() 圖1是一個損失函數的等高線圖,顯示了不同最優化算法的直觀效果,其中基于動量的方法出現了折返的情況。圖2展示了一個馬鞍狀的最優化地形,其中,SGD很難突破對稱性,一直卡在頂部;RMSProp等方法能夠朝著馬鞍方向繼續前進,雖然該方向梯度小,但是由于 RMSProp方法中的分母項的存在,可以提高在該方向的學習率。
最后,附幾篇拓展文章:
|
|