M5.2 追一隻自己也在跑的狗:移動目標、EMA 與 Stop-Gradient
本篇重用M1.1從鞋子猜身高:Conditional Expectation·M3.0醉漢一小時後在哪:Random Walk 到 Brownian Motion
一隻不肯停的狗
公園裡一隻狗在跑。你戴著一個定位手環的接收器,每秒收到它一個位置——但手環很便宜,每個讀數都有大約 3 公尺的隨機誤差。你想知道狗現在在哪,好走過去接它。
最直接的做法:相信最新的那個讀數。結果是你每秒都被 3 公尺的雜訊甩來甩去,方向一直改。第二種做法:把過去十秒的讀數平均。雜訊被壓下去了,但狗跑得快——十秒前它在二十公尺外,你的平均永遠指向它已經離開的地方,你一直追過頭。
有沒有一種介於兩者之間的做法?它要「記得」多久?請先用直覺回答:如果狗跑得更快,你該記得更久還是更短?如果雜訊更大呢?寫下你有多確定。
課堂提問Q1
翻成數學。「狗的真實位置」與「讀數」各是什麼?「記得多久」可以用一個什麼樣的規則寫出來,讓它不需要真的存十秒的資料?
先想一想,再展開看整理後的答案
課堂上會先把真實位置寫成 (一條會動的曲線),讀數寫成 , 是均值 0、標準差 公尺、彼此獨立的雜訊。我們想要的估計 要同時滿足兩件矛盾的事:接近 (跟得緊)、又不被 甩動(雜訊小)。
「記得多久」若用「存最近 個讀數取平均」來寫,要存 個數、每秒重算。有一個更簡潔的規則,只存一個數:
每秒把「上一刻的估計」與「這一刻的讀數」按 混合。 是「只信最新讀數」, 是「幾乎不更新」。這叫 exponential moving average(EMA)。它「記得多久」由 一個數決定——下一節會把這個「多久」算出來。
先抓住這個畫面:一桶會漏的水
把 想成一桶水的水位。每秒倒進 桶新水(今天的讀數 ),同時舊水只留下 的比例。一週前倒進去的水,現在只剩 ——早就漏光了;一秒前的還剩 。所以水位是過去所有讀數的加權平均,權重按時間往回幾何遞減:越近的越重,越遠的越輕,沒有一個硬的截止點。
控制漏得多快。 時,十秒前的水只剩 ,二十秒前剩 ——「有效記憶」大約十秒。 時有效記憶約一百秒。這比「存最近 個」好在兩件事:只要一個數的儲存空間,而且沒有「第 個算、第 個不算」那種突然的切換。
寫成數學:一個係數,兩個代價
把遞迴展開(代入 ,再代入 ,…):
權重和為 1,所以它是一個合法的加權平均。有效記憶長度取權重的平均延遲:。
現在把兩個代價算出來。代入 ,EMA 是線性的,所以 。
雜訊的代價。 第二項是獨立零均值雜訊的加權和,變異數是權重平方和乘 (M3.0 的「變異數相加」):
:雜訊標準差變成 ,3 公尺壓到 0.7 公尺。 越接近 1 壓得越多。
滯後的代價。 若狗以等速 跑,,第一項變成 。EMA 永遠指向狗「有效記憶長度」之前的位置,落後 。、狗每秒跑 2 公尺:落後 18 公尺。
兩個代價往相反方向動:
是「跟多緊」與「多平滑」之間唯一的旋鈕。 狗跑得快( 大)就該把 調小、記得短;雜訊大( 大)就該調大、記得長。最佳的 讓兩項加起來最小——它有 closed form,但更重要的是它由 與 的比值決定,不是一個放諸四海皆準的常數。
展開細節有偏的起點、Adam 的修正、與 Polyak averaging
遞迴從 m₀ = 0 開始時,m_t = (1−β)Σ_{k<t} βᵏ x_{t−k} 的權重和是 1 − βᵗ < 1——前面幾步的估計被系統性地拉向 0。Adam [3] 的「bias correction」就是把 m_t 除以 (1 − βᵗ),讓權重和回到 1;t 大了以後這個修正自動消失。
另一個常見的用法是把 EMA 套在一串會收斂的估計上(Polyak & Juditsky [2]):如果 x_t 本身是某個演算法的第 t 步迭代、它在真值附近抖動,那 EMA 把抖動壓掉、留下更穩的答案——這時「目標會動」的問題反而是好事:目標最終不動了,滯後也就消失。實務上把 β 設成 0.999 甚至更接近 1 的「權重平均」就是這個用法。
一個更危險的情境:追的是自己的影子
上面的狗有一個好性質:它的位置 不會因為你怎麼估而改變。現在換一個情境。
你在訓練一個估計器 ,它的訓練目標是由它自己的輸出定義的——例如「 應該接近 的某個變換」。這種「用自己的預測當作自己的目標」叫 bootstrap。強化學習裡的 Q-learning( 的目標是 )、自監督學習裡「兩個視角的表徵要一致」的方法(BYOL [4])都是這種結構。
它有一個致命的平凡解:讓 輸出常數。常數對常數,目標與預測完全一致,loss 為零,但什麼都沒學到。狗的比喻裡,這相當於狗的位置是由你的估計定義的——你站著不動,狗就「在你腳下」。
兩個技術一起避開這個坑:
- Stop-gradient。 計算目標時把它當成常數,不讓梯度流過去:。這樣「把目標移過來」這條捷徑被切斷了,只剩「把預測移過去」。
- 慢速目標(EMA target)。 目標不用當前的 ,用它的 EMA , 很接近 1(0.99–0.999)。目標網路是一個「落後、平滑」的自己——就是這一篇的 EMA,但這裡滯後是想要的:它讓目標在幾百步內幾乎不動,把一個「追自己」的問題變回「追一隻跑得很慢的狗」。DQN [5] 用的「target network 每隔 步複製一次」是同一個想法的硬截止版。
兩者的分工:stop-gradient 決定梯度往哪個方向流(只更新預測端),EMA 決定目標動多快。少了前者,最速下降會直接把目標拉向預測;少了後者,目標每步都跳、訓練震盪。
回到公園:直覺對了,數字現在有了
回答起點問題。狗跑得快 → 該調小(記得短,落後 才不會太大);雜訊大 → 該調大(雜訊標準差是 )。兩者衝突時,最佳 由 決定:狗每秒 2 公尺、雜訊 3 公尺時,把總誤差 對 掃一遍,最小值落在 附近(落後約 1.1 公尺、雜訊約 2.1 公尺; 則是落後 2 公尺、雜訊 1.7 公尺,總誤差差不多);狗若停下來(),最佳 。
這個判斷依賴的假設:狗的速度大致穩定(等速假設;急轉彎時任何 都會在轉彎處落後一段)、雜訊獨立且零均值(若手環有系統性偏差,EMA 會忠實地保留它)、以及目標不受估計影響。最後一點失效時——目標由估計者定義——就要把 stop-gradient 與慢速目標拿出來。
回到公園:跑一次,讓狗急轉彎一次,然後追自己的影子一次
import numpy as np
rng = np.random.default_rng(0)
T, v, sigma = 200, 2.0, 3.0
mu = v * np.arange(T) # 狗等速直線
x = mu + sigma * rng.standard_normal(T) # 帶雜訊的讀數
def ema(x, beta):
m = np.empty_like(x); m[0] = x[0]
for t in range(1, T): m[t] = beta*m[t-1] + (1-beta)*x[t]
return m
for beta in [0.0, 0.5, 0.9]:
m = ema(x, beta); err = m[50:] - mu[50:]
print(beta, err.mean().round(1), err.std().round(2), # 實測 滯後 / 雜訊
(-v*beta/(1-beta)), (sigma*np.sqrt((1-beta)/(1+beta))).round(2)) # 理論 滯後 / 雜訊
# 破壞 1:狗在 t=100 急轉彎(速度反向)
mu2 = np.where(np.arange(T) < 100, mu, 2*mu[100] - mu)
m = ema(mu2 + sigma*rng.standard_normal(T), 0.9); print(np.abs(m - mu2)[100:130].max().round(1)) # 轉彎後最大偏差約 18 公尺、再花約 10 步追回
# 破壞 2:追自己的影子——目標 = 自己的輸出,沒有 stop-gradient
theta = 5.0
for _ in range(100): target = theta; theta -= 0.1 * 2*(theta - target) # 梯度為零,theta 永遠不動:平凡解
print(theta)
前三行: 時實測落後 公尺、雜訊 公尺,與理論值 、 吻合; 落後 2、雜訊 1.7。急轉彎: 的 EMA 在轉彎後的最大偏差約 18 公尺——轉彎前它落後 18 公尺、轉彎那一刻反而「超前」18 公尺,然後要花約 步才追回來;「等速」的假設破了,公式的滯後項在那幾秒失效。最後那個「追自己的影子」:目標就是自己,梯度恆為零, 停在 5——loss 是零,什麼也沒學。
先消化一下
參考文獻
- Brown, R. G. Smoothing, Forecasting and Prediction of Discrete Time Series. Prentice-Hall, 1963.(exponential smoothing 的系統性整理;滯後與平滑的取捨。)
- Polyak, B. T., Juditsky, A. B. Acceleration of Stochastic Approximation by Averaging. SIAM Journal on Control and Optimization 30(4), 1992.(對迭代序列做平均可以壓掉抖動——展開框裡的用法。)
- Kingma, D. P., Ba, J. Adam: A Method for Stochastic Optimization. ICLR 2015.(EMA 的 bias correction 。)
- Grill, J.-B. et al. Bootstrap Your Own Latent: A New Approach to Self-Supervised Learning. NeurIPS 2020.(EMA 目標網路 + stop-gradient 避開平凡解的代表性例子。)
- Mnih, V. et al. Human-level Control through Deep Reinforcement Learning. Nature 518, 2015.(target network:每隔 步複製一次的「硬截止」版慢速目標。)