您當前的位置:首頁 > 體育

nn中的optimizers

作者:由 馬東什麼 發表于 體育時間:2022-01-15

w表示nn的權重,learning rate為學習率,g為梯度更新量

原文部分來自:

其它來自官方文件以及一些文章

使用我覺得好理解合理的解釋總結了一下

0 初始:single sample,minibatch,whole batch

因為單樣本更新,mini-batch更新,whole batch 更新適用於所有的optimizers,並且很多時候經常把 樣本的更新級別和optimizer放在一起說,所以這裡先說下這部分吧。

nn中的optimizers

single sample 收斂慢,震盪厲害,不穩定,視訊記憶體壓力幾乎沒有,容易跳出區域性最優但也不容易收斂到相對最優點;

whole batch 收斂快,震盪小,穩定,視訊記憶體壓力很大,海量資料基本不可能,容易收斂到區域性最優但不容易跳出區域性最優到達相對更優點;

mini batch 折中的選擇,具體效果根據不同的batch size而不同。

sgd,momentum,nesterove 來自:

1 SGD和SGDM:

w(t) = w(t-1) - learning_rate * g(t)

萬物始祖。

缺陷:

1。對待所有nn的weights一視同仁,然而input中的features本身會因為稀疏(例如推薦中某些category出現的次數很少,某些category出現的次數很多)等問題而導致相同epochs下不同的區域性weights的訓練程度不一的問題,例如在nlp中,高頻詞的embdding weights和低頻詞的embedding weights 受到訓練的次數都不一樣;

2。nn由於其複雜的非線性結構導致loss function往往是非凸的,非凸的loss function的最佳化路徑存在較多的區域性最優點和大量的鞍點,導致模型提早收斂無法跳出。

這裡的change根據不同的optimizers的設計而有所不同。

SGDW就是SGD+weight decay

另外,tfa中提供的tfa。optimizers。extend_with_decoupled_weight_decay可以和任意的optimizer搭配實現 weight decay版的optimizer

關於l2正則和weight decay的區別可見:

2 SGD with Momentum

momentum(t) = u * velocity(t-1) - learning_rate * g(t)

w(t) = w(t-1) +momentum(t)

初始momentum為0,u 為衰減係數,常用0。95,可調的超引數。

使用動量替代了單純的梯度,引入了物理的慣性(啟發式的方法),是為了緩解原始的sgd的

第二個缺陷

引入的啟發式的最佳化方法。

優點:

momentum本質上是對g(t)的指數平均,能夠在最佳化的過程中較好的考慮歷史的最佳化方向,當前g(t)方向和歷史的最佳化方向保持一致時,則當前的momentum(t)更大,從而起到加速的作用,當前g(t)方向和歷史最佳化方向差異較大時,則當前的momentum(t)將變小,從而起到減速的作用。

這裡的加速和減速作用直接傳導給learning rate,

本質上其實可以看作是對 learning rate的自動調整(但是還沒有細緻到對每個引數weights間接使用不同的學習率,對於momentum而言,learning rate雖然是間接變化的,但是是對於全體trainable 引數 一視同仁的)

。所以優點為:

1。下降初期,g(t)整體的方向較為一致,起到加速作用;

2。下降中後期,累積的momentum 有助於跳出區域性最優點或鞍點;

3。最重要的,自適應調整學習率,平滑學習率變動曲線,如下圖綠色(本質上和time series forecasting中的指數平均策略起到的效果類似)

nn中的optimizers

缺點:

1。衝的太猛,相對下面提到的nesterov震盪更多。

2。並沒有針對不同的引數自適應的間接使用不同的學習率

3。 SGD with Nesterov Momentum

nn中的optimizers

nn中的optimizers

momentum'(t) = u * momentum(t-1) - learning_rate * g(t)

w'(t) = w(t-1) +momentum'(t)

(這一切都是為了預先得到w‘(t),從而計算處g’(t)。而後就和momentum完全一樣:)

momentum(t) = u * momentum(t-1) - learning_rate * g'(t)

w(t) = w(t-1) + momentum(t)

可以認為

Nesterov Momentum 是引入了類似

look ahead

機制的 Momentum。簡單來說就是

先使用momentum的方法對權重進行“擬”更新,然後計算擬更新之後的新的梯度計算結果,將這個結果帶入原始的momentum的更新公式中替換原始的梯度計算結果

其背後的直覺在於當前的更新不僅取決於歷史的累積,也受到未來的變化所影響,因此我們在更新引數的過程中不僅要考慮歷史的積累也要考慮未來可能的變化。

nn中的optimizers

例如上圖藍色表示momentum,綠色表示nesterov,棕色和紅色表示nesterov對momentum的修正過程。

優點:

緩解了mometum衝的太猛的問題;

缺點:

並沒有針對不同的引數自適應的間接使用不同的學習率

tf目前是把三者的實現統一放到 SGD裡了:

nn中的optimizers

3。 Adagrad

算是大家熟悉的演算法裡面第一個引入自適應權重調整的optimizer了。

n(t)=n(t-1)+v

*

g(t)**2 (v是一個超引數)

w(t)=w(t-1)-learning_rate * g(t)

/(sqrt(nt)+eplison) (eplison主要用於避免出現除0的問題,無實際意義)

終於能夠自適應的對不同的引數間接使用不同的學習率了。

對於g(t)而言,g(t)是nn中的引數值的梯度更新量構成的梯度矩陣,梯度更新量越大的引數w對應的n(t)越大,否則越小,因此在nn的引數更新時,越大的n(t)會導致梯度更新量越小,越小的n(t)會導致梯度更新量越大,從而達到不頻繁更新引數每次梯度更新量大,頻繁更新引數每次梯度更新量小的目的。

優點:

1。對於稀疏的input具有較好的“平衡”訓練的效果(例如推薦中的高頻category和低頻category的embedding引數更新的問題);

nn中的optimizers

引數更新量越大,則後期的新的更新量越小

缺點:

1。緩解了sgd的問題1,但是又沒有考慮sgd的問題2了,動量部分欠考慮;

2。n(t)=n(t-1)+v*g(t)**2,n(t

)是不斷遞增的,當遞增到很大的值時,會使得梯度更新量趨於0從而等同於提前停止引數更新;

(補充,所謂的自適應針對不同權重進行不同程度的權重更新,本質上的思路是將梯度更新公式和權重本身的取值透過某種方式關聯起來)

4。 Adadelta

對照不帶動量的rmsprop:

n(t)=v*n(t-1)+(1-v)*g(t)**2

w(t)=w(t-1)-learning_rate

*g(t)

/(sqrt(nt)+eplison)

adadelta的公式為:

n(t)=v*n(t-1)+(1-v)*g(t)**2

w(t)=w(t-1)-learning_rate*g(t)

/(sqrt(n(t))+eplison)

可以看到二者的公式完全一致,原作中作者經過了一定的處理,使用近似牛頓迭代法近似之後公式變成了:

根據adadelta 原論文的部分的描述:

Correct Units with Hessian Approximation The units in SGD and Momentum relate to the gradient, not the parameter:

\Delta x \sim g \sim \frac{\partial f}{\partial x} \sim \frac{1}{units\ of \ x}

( 4 ) In contrast, second order methods such as Newton’s method that use Hessian information or an approximation to the Hessian do have the correct units for the parameter updates:

\Delta x \sim H^{-1}g \sim \frac{\frac{\partial f}{\partial x}}{\frac{\partial^2 f}{\partial x^2}} \sim units\ of \ x

( 5 ) The

H^{-1}g = \Delta x

can derive a equation that

\frac{1}{\frac{\partial^2 f}{\partial x^2}} = \frac{\Delta x}{\frac{\partial f}{\partial x}}

。 Hence , the equation (3) can be transformed to,

\Delta x_t = -\frac{RMS[\Delta x]_{t-1}}{RMS[g]_t}\ g_t

( 6 )

透過

近似牛頓迭代法

,使用 RMS(delta_x(t-1))) 直接代替了learning rate,從而使得adadelta脫離了learning rate這個引數的設定。我們令公式6中的分子部分為delta(t)則 近似之後的adadelta為:

nn中的optimizers

https://pytorch。org/docs/stable/generated/torch。optim。Adadelta。html torch官網

按照上文的格式,這裡的更新過程是這樣的:

n(t)=v*n(t-1)+(1-v)*g(t)**2

delta(t)=(sqrt(m(t-1))+eplison)/(sqrt(n(t))+eplison) (這一項直接替代learning rate)

m(t)= v*m(t-1)+(1-v)* delta(t)**2

w(t)=w(t-1)-delta(t)*g(t)

(torch和tf的實現中為了保持api的一致性,仍舊存在learning rate的引數,實際使用中將learning rate設定為1即可保持和adadelta原文一致的效果)

優點:

不需要學習率了(tf的預設learning rate=1,等於就是不用learning rate了),

缺點:

1 仍舊未考慮動量(說實話,感覺這些缺點也不算缺點吧,額外加入動量模組其實就行了);

nn中的optimizers

5。 RMSprop

如果不考慮nesterov動量,則

n(t)=v*n(t-1)+(1-v)*g(t)**2

w(t)=w(t-1)-learning_rate*g(t)/sqrt(n(t)+eplison)

可以看到相對於adagrad的改變在於,n(t)的部分 對歷史的n(t)和當前的g(t)**2 使用了加權機制而不是簡單的對g(t)**2進行指數加權。

可以看作是adagrad的擴充套件版。

值得一提的是,在tf的實現中,為rmrprop提供了nesterove動量的支援

(動量,nesterove動量是可以靈活搭配的,搭配sgd就是常規的momentum和nesterove的optimizer,也可以搭配adam等optimizer)。

g(t)=g'(t)

(同樣的思路,先按照rmsprop不帶nesterove的動量的公式“擬”更新權重係數,然後在新的權重係數上才最終計算真正參與到實際權重更新公式中的g'(t),達到look ahead的效果)

n(t)=v*n(t-1)+(1-v)*g(t)**2 #nesterove其實就是這麼簡單,就是lookahead

w(t)=w(t-1)-learning_rate

*

g(t)/(sqrt(nt)+eplison)

nn中的optimizers

優點:

引入衰減機制,解決了adagrad中n(t)不斷累加變得太大導致提早停止訓練的問題。

加入了nesterov動量支援之後,終於同時考慮動量和自適應學習率了。

6 Adam和Adam with amsgrad

帶有

魔改版momentum

的rmsprop(這裡不考慮tf中實現的加入nasterov的rmsprop而是原始的rmsprop,同時需要注意,其實是對momentum做了一點魔改的)

對照 rmsprop:

n(t)=v*n(t-1)+(1-v)*g(t)**2

w(t)=w(t-1)-learning_rate *g(t)/(sqrt(nt)+eplison)

和momentum:

momentum(t)=u*momentum(t-1)+g(t)

可以得到Adam:

n(t)=beta2*n(t-1)+(1-beta2)*g(t)**2

n(t)=n(t)/(1-beta2**t) (偏置矯正,因為m(t)和n(t)初始為0,話說adam之前的那些也沒做這個矯正。。)

m(t)=beta1*m(t-1)+(1-beta1)*g(t) (這裡和momentum的結果還是有一些不同的,momentum並不對g(t)項進行修改,即經典的momentum並不存在1-bata1這一項)

m(t)=m(t)/(1-beta1**t)

w(t)=w(t-1)-learning_rate*m(t)/sqrt(n(t)+eplison) * g(t)

(beta1和beta2 是兩個超引數用於調節指數移動平均的程度)

最通用的optimizer了。

優點:

結合了Adagrad善於處理稀疏梯度和RMSprop善於處理非平穩目標的優點

對記憶體需求較小

為不同的引數計算不同的自適應學習率,並且學習率由於 learning_rate*m(t)/sqrt(n(t)+eplison) 形成動態約束,使得最終的實際的learning rate 限定在一個相對穩定的範圍之內。

也適用於大多非凸最佳化 - 適用於大資料集和高維空間

缺點:

對於adagrad而言,

n(t)=n(t-1)+v*g(t)**2

w(t)=w(t-1)-learning_rate/(sqrt(nt)+eplison) *g(t)(eplison主要用於避免出現除0的問題,無實際意義)

其中,n(t)是不斷單調遞增的,這就導致最終 learning_rate/(sqrt(nt)+eplison) 必然是單調遞減的,

至少可以保證模型必然收斂;

而 rmsprop,adadelta,adam中,統一的形式都是:

n(t)=v*n(t-1)+(1-v)*g(t)**2

n(t)的變化並不是線性的,會出現n(t)的計算結果時大時小,

從而使得

實際的 學習率 發生震盪

,影響模型的收斂。(說老實話這個其實可以透過人工設定lr的衰減的方式來緩解,後期 learning rate 透過 learning rate schedule的方式降低到很小的值,則整體 的 實際學習率即使震盪,對於模型的影響也是微乎其微的)

nn中的optimizers

為了解決這個問題,引入了

amsgrad

,如上圖,其實就是

n(t)=max(beta2*n(t-1)+(1-beta2)*g(t)**2,n(t-1))

保證n(t)是非遞減的。

7 Adamax

和amsgrad類似的思路,希望保證n(t)非遞減,仍舊是對n(t)這個二階矩估計下手

adam with amsgrad:n(t)=max(beta2*n(t-1)+(1-beta2)*g(t)**2,n(t-1))

adamax:n(t)=max(beta2*n(t-1),g(t)**2)

nn中的optimizers

提到對於帶有embedding的模型可能效果會更好。

補充:一階矩和二階矩

什麼是一階矩和二階矩?_百度知道

8 Nadam

Adam with nesterov,公式就不寫了

nn中的optimizers

adam“擬”更新得到w‘(t),從而得到look ahead 的g’(t),然後將g‘(t)代替g(t) 再重新使用adam計算一遍得到t時刻的w的實際的權重更新結果。

9 FTRL

線上梯度下降平常基本用不太上,pass,有需要再研究

TF中的optimizers介紹完畢,下面是torch的:

AdamW

Implements AdamW algorithm。

SparseAdam/lazyadam

Implements lazy version of Adam algorithm suitable for sparse tensors。

ASGD

Implements Averaged Stochastic Gradient Descent。

LBFGS

Implements L-BFGS algorithm, heavily inspired by minFunc。

RAdam

Implements RAdam algorithm。

Rprop

Implements the resilient backpropagation algorithm。

10 RAdam 和 warmup

tf的warm up實現,可以搭配現有的learning rate schedule使用。

Radam中提到了warm up這個 tricky的learning rate schedule的問題,我們常規的思路是,初始的時候nn的loss很大所以需要大的學習率來快速達到一個不錯的水平,然後再用小learning rate 慢慢調。而warm up則反過來,從一個小的學習率逐步增大到我們設定的初始學習率。當然,這兩個策略是可以結合使用的,即

warmup預熱+learning rate schedule of decay

warmup策略和momentum類似,是一個可以靈活搭配的trick,後面會放到learning rate schedule中總結。

至於warm up為什麼work,可以參考這篇:

作者指出,儘管每個人都在朝著擁有快速穩定的最佳化演算法的目標努力,但自適應學習率最佳化器(包括Adam、RMSProp等)都面臨著陷入糟糕的區域性最佳化(如果沒有實現warmup方法的話)的風險。因此,幾乎每個人都使用某種形式的warmup(FastAI在Fit_One_Cycle中內建了warmup功能)……但是為什麼需要warmup呢?

由於目前對人工智慧社群中warmup啟發式的潛在原因甚至最佳實踐的理解有限,作者試圖揭示這個問題的基礎。他們發現,根本問題在於

自適應學習率最佳化器的方差太大

,特別是在訓練的早期階段,並且基於有限的訓練資料進行過多的跳躍,從而會陷入較差的區域性最佳化。

因此,當最佳化器只處理有限的訓練資料時,warmup(初始訓練階段,學習速度要低得多)是自適應最佳化器抵消過多差異的必要條件。

下面是一個視覺化的演示,展示了在沒有warmup的情況下Adam最初的情況——在10次迭代中,梯度分佈很快就被打亂了:

nn中的optimizers

注意,在沒有warmup的情況下,初始正態分佈是如何迅速扭曲的。

這裡作者認為 adam 這類 自適應的最佳化器的learning rate方差太大。看下adam的公式:

n(t)=beta2*n(t-1)+(1-beta2)*g(t)**2

n(t)=n(t)/(1-beta2**t) (偏置矯正,無偏估計)

m(t)=beta1*m(t-1)+(1-beta1)*g(t)

m(t)=m(t)/(1-beta1**t)

w(t)=w(t-1)-learning_rate*m(t)/sqrt(n(t)+eplison) * g(t)

(beta1和beta2 是兩個超引數用於調節指數移動平均的程度)

自適應最佳化器的“真實” learning rate =超引數設定的learning_rate * 不同自適應最佳化器使用的自適應策略,例如adam中:

真實的leanring rate=learning_rate*m(t)/sqrt(n(t)+eplison)

而所謂的學習率方差大則是因為這裡的自適應最佳化器使用的自適應策略導致了 真實learning rate的變化是時大時小從而影響收斂。

而Radam的初衷在於怎麼處理由於自適應策略導致的learning rate的不規則變化。

Radam=Rectified Adam=動態warmup(sgd momentum部分)+ 自適應方差調整下的adam

具體可見:

11 ranger

radam = tfa。optimizers。RectifiedAdam()

ranger = tfa。optimizers。Lookahead(radam, sync_period=6, slow_step_size=0。5)

11 AdamW

Adamw=adam+weight decay!=adam+l2 regularization

torch中的optimizers基本介紹完畢,最後是tensorflow addons中的其它的一些optimizers

AdaBelief

COCOB

ConditionalGradient

LAMB

NovoGrad

ProximalAdagrad

Yogi

Rezero

LBFGS

Rprop

ASGD

SparseAdam/lazyAdam

(有空再說吧,感覺這些基本沒遇到過)

標簽: rate  Learning  momentum  更新  eplison