https://www.cnblogs.com/wuliytTaotao/p/9479958.html
目錄
1. 用滑動平均估計局部均值
2. TensorFlow中使用滑動平均來更新變量(參數)
3. 滑動平均為什么在測試過程中被使用?
1. 用滑動平均估計局部均值
滑動平均(exponential moving average),或者叫做指數加權平均(exponentially weighted moving average),可以用來估計變量的局部均值,使得變量的更新與一段時間內的歷史取值有關。
變量vv在tt時刻記為 vtvt,θtθt 為變量 vv 在 tt 時刻的取值,即在不使用滑動平均模型時 vt=θtvt=θt,在使用滑動平均模型后,vtvt 的更新公式如下:
上式中,β∈[0,1)β∈[0,1)。β=0β=0 相當於沒有使用滑動平均。
假設起始 v0=0v0=0,β=0.9β=0.9,之后每個時刻,依次對變量 vv 進行賦值,不使用滑動平均和使用滑動平均結果如下:
表 1 三種變量更新方式
t | 不使用滑動平均模型,即給vv直接賦值θθ | 使用滑動平均模型, |
使用滑動平均模型, |
---|---|---|---|
0, 1, 2, ... , 35 | [0, 10, 20, 10, 0, 10, 20, 30, 5, 0, 10, 20, 10, 0, 10, 20, 30, 5, 0, 10, 20, 10, 0, 10, 20, 30, 5, 0, 10, 20, 10, 0, 10, 20, 30, 5] | [0, 1.0, 2.9, 3.61, 3.249, 3.9241, 5.5317, 7.9785, 7.6807, 6.9126, 7.2213, 8.4992, 8.6493, 7.7844, 8.0059, 9.2053, 11.2848, 10.6563, 9.5907, 9.6316, 10.6685, 10.6016, 9.5414, 9.5873, 10.6286, 12.5657, 11.8091, 10.6282, 10.5654, 11.5089, 11.358, 10.2222, 10.2, 11.18, 13.062, 12.2558] | [0, 10.0, 15.2632, 13.321, 9.4475, 9.5824, 11.8057, 15.2932, 13.4859, 11.2844, 11.0872, 12.3861, 12.0536, 10.4374, 10.3807, 11.592, 13.8515, 12.7892, 11.2844, 11.1359, 12.145, 11.9041, 10.5837, 10.5197, 11.5499, 13.5376, 12.6248, 11.2844, 11.1489, 12.0777, 11.8608, 10.6276, 10.5627, 11.5365, 13.4357, 12.5704] |
圖 1:三種變量更新方式
Andrew Ng在Course 2 Improving Deep Neural Networks中講到,tt 時刻變量 vv 的滑動平均值大致等於過去 1/(1−β)1/(1−β) 個時刻 θθ 值的平均。這個結論在滑動平均起始時相差比較大,所以有了Bias correction,將 vtvt 除以 (1−βt)(1−βt) 修正對均值的估計。
加入了Bias correction后,vtvt 和 v_biasedtv_biasedt 的更新公式如下:
tt 越大,1−βt1−βt 越接近 1,則公式(1)和(2)得到的結果 (vtvt 和 v_biasedtv_biasedt)將越來越近,如圖 1 所示。
當 ββ 越大時,滑動平均得到的值越和 θθ 的歷史值相關。如果 β=0.9β=0.9,則大致等於過去 10 個 θθ 值的平均;如果 β=0.99β=0.99,則大致等於過去 100 個 θθ 值的平均。
滑動平均的好處:
占內存少,不需要保存過去10個或者100個歷史 θθ 值,就能夠估計其均值。(當然,滑動平均不如將歷史值全保存下來計算均值准確,但后者占用更多內存和計算成本更高)
2. TensorFlow中使用滑動平均來更新變量(參數)
滑動平均可以看作是變量的過去一段時間取值的均值,相比對變量直接賦值而言,滑動平均得到的值在圖像上更加平緩光滑,抖動性更小,不會因為某次的異常取值而使得滑動平均值波動很大,如圖 1所示。
TensorFlow 提供了 tf.train.ExponentialMovingAverage 來實現滑動平均。在初始化 ExponentialMovingAverage 時,需要提供一個衰減率(decay),即公式(1)(2)中的 ββ。這個衰減率將用於控制模型的更新速度。ExponentialMovingAverage 對每一個變量(variable)會維護一個影子變量(shadow_variable),這個影子變量的初始值就是相應變量的初始值,而每次運行變量更新時,影子變量的值會更新為:
公式(3)中的 shadow_variable 就是公式(1)中的 vtvt,公式(3)中的 variable 就是公式(1)中的 θtθt,公式(3)中的 decay 就是公式(1)中的 ββ。
公式(3)中,decay 決定了影子變量的更新速度,decay 越大影子變量越趨於穩定。在實際運用中,decay一般會設成非常接近 1 的數(比如0.999或0.9999)。為了使得影子變量在訓練前期可以更新更快,ExponentialMovingAverage 還提供了 num_updates 參數動態設置 decay 的大小。如果在初始化 ExponentialMovingAverage 時提供了 num_updates 參數,那么每次使用的衰減率將是:
這一點其實和 Bias correction 很像。
TensorFlow 中使用 ExponentialMovingAverage 的例子:code (如果 GitHub 無法加載 .ipynb 文件,則將 .ipynb 文件的 URL 復制到網站 https://nbviewer.jupyter.org/)
3. 滑動平均為什么在測試過程中被使用?
滑動平均可以使模型在測試數據上更健壯(robust)。“采用隨機梯度下降算法訓練神經網絡時,使用滑動平均在很多應用中都可以在一定程度上提高最終模型在測試數據上的表現。”
對神經網絡邊的權重 weights 使用滑動平均,得到對應的影子變量 shadow_weights。在訓練過程仍然使用原來不帶滑動平均的權重 weights,不然無法得到 weights 下一步更新的值,又怎么求下一步 weights 的影子變量 shadow_weights。之后在測試過程中使用 shadow_weights 來代替 weights 作為神經網絡邊的權重,這樣在測試數據上效果更好。因為 shadow_weights 的更新更加平滑,對於隨機梯度下降而言,更平滑的更新說明不會偏離最優點很遠;對於梯度下降 batch gradient decent,我感覺影子變量作用不大,因為梯度下降的方向已經是最優的了,loss 一定減小;對於 mini-batch gradient decent,可以嘗試滑動平均,畢竟 mini-batch gradient decent 對參數的更新也存在抖動。
設 decay=0.999decay=0.999,一個更直觀的理解,在最后的 1000 次訓練過程中,模型早已經訓練完成,正處於抖動階段,而滑動平均相當於將最后的 1000 次抖動進行了平均,這樣得到的權重會更加 robust。