概念
之前一直對“權重衰減”和“學習率衰減”存在誤解,我甚至一度以為它們是同一個東西,以至於使用的時候感覺特別困惑。在優化器中使用了“權重衰減”,竟然發現模型的准確率下降了,假如它們是同一個東西,至少應該是學得慢,而不是學壞了。因此,專門查了一下資料,了解兩者的區別,這篇隨筆做一下記錄。
- 權重衰減
權重衰減 (weight decay),是一種正則化的方法,應用了權重衰減的神經網絡,最終某些權重會變成零 [1],相當於輸入在這個神經元上會被拋棄。神經網絡中某些權重歸零,表示模型的復雜度下降了,多了一個零,少了一個參數。
- 學習率衰減
學習率衰減 (learning rate decay) 就是調小學習率,使到損失可以進一步減小。如果整個優化過程,學習率一直保持較大的數值,那么在損失可能在局部最小值的周圍震盪,而又到不了局部最小。將學習率變小,學習的步長變小了,使到損失可以到達局部最小。
權重衰減
為什么叫做權重衰減
有的時候(因為另一些時候不叫),權重衰減又叫做 L2 正則化,意思是在損失函數上面加上一個 L2 正則項。
梯度下降的時候,權值的更新公式將變為如下:
如果一個權值每次梯度下降的時候,梯度都很小,甚至沒有,如果我們將公式忽略掉,經過多次更新,可以看到權值將指數衰減(每次都乘以一個數),最終趨向於零。趨向於零的速度,取決於系數,如果是 0.01,那么 100 次迭代,每次更新為原來的 0.99,100 次后權值會變為原來的 0.36。
權重衰減應該設置多少
這個屬於煉丹的參數,在 0 到 1 之間即可。不知道設置多少,就設置 0.01 或 0.001 吧,保守一點 [4]。如果有足夠多的時間或者 GPU,那就搜索一下咯。
權重衰減和 Adam
[3] 改進了權重衰減。對於 Adam 優化器,如果我們還是像前面使用的 L2 正則化那樣,在損失函數后面加正則項,梯度還是那樣算,但是一頓算之后,權重衰減就變得和原來的“衰減”不太相同了。沒有人保證在一頓算之后,權重更新的公式還是權重衰減的。所以 [3] 提出直接在權重更新的公式上面加上更新項,這樣才符合權重衰減的名字嘛。Pytorch 中 Adam 的 weight decay 用的是 L2 正則化,AdamW 是 [3] 提出的方法。鏈接 [2] 對這個話題進行了一些討論,可以看看。
學習率衰減
Pytorch 中提供了調整學習率的方法。
- 可以使用 ExponentialLR 來使到學習率指數衰減,每次學習率乘以一個倍數。
- 可以用 ReduceLROnPlateau,在訓練幾個 epoch 之后,如果仍然不提高,那么將衰減學習率,使其可以達到局部最小。
學習率
學習率衰減的本質,其實是一種調整學習率的策略,將學習率往小的方向調整。拋開學習率衰減,我在查閱資料的過程中,還發現了周期性學習率(Cyclical Learning Rate)這個東西。在整個學習的過程中不斷調整學習率,學習率在周期函數上變化,時大時小,屬於一種煉丹小技巧。CLR 的論文說可以避免再微調和減少訓練的 epoch。[5]
學習率衰減和 Adam
Adam 自己就是會動態改變學習率的,那我們還需要學習率衰減嗎?
可以用,煉丹小技巧 +1。
[6] 指出,設置了學習率的 Adam,可以保證 Adam 每個參數的更新的時候,不會超過這個上界。使用學習率衰減來減小更新的步長。
總結
查閱完資料,總結了一下之后,我發現,這 TM 就是兩個東西,完全不同的兩個東西。一個是為了防止過擬合,一個就是為了過擬合啊!
參考鏈接
[1] https://stats.stackexchange.com/questions/29130/difference-between-neural-net-weight-decay-and-learning-rate
[2] https://towardsdatascience.com/why-adamw-matters-736223f31b5d
[3] https://arxiv.org/abs/1711.05101
[4] https://machinelearningmastery.com/how-to-reduce-overfitting-in-deep-learning-with-weight-regularization/
[5] https://zhuanlan.zhihu.com/p/54745666
[6] https://stackoverflow.com/questions/39517431/should-we-do-learning-rate-decay-for-adam-optimizer
[7] https://pytorch.org/docs/stable/optim.html#:~:text=adjust learning rate-,torch.optim.lr_scheduler,-provides several methods