Pytorch – AdaGrad、RMSprop、AdaDelta について解説

概要

Pytorch で使用できる最適化アルゴリズム AdaGrad、RMSProp、RMSpropGraves、Adadelta について解説します。

Adagrad

AdaGrad はこれまでのステップの勾配の大きさを記録し、学習率を調整するアルゴリズムです。

torch.optim.Adagrad(params, lr=0.01, lr_decay=0, weight_decay=0, initial_accumulator_value=0, eps=1e-10)
Python
パラメータ 意味 初期値 範囲
lr 学習率 0.01 0以上の小数
lr_decay 学習率の減衰率 0 0以上の小数
weight_decay weight decay の係数 0 0以上の小数
initial_accumulator_value 累積和の初期値 0 0以上の小数
eps epsilon 1e-10 0以上の小数

Optimizer の状態

パラメータ 意味 サイズ
sum 勾配の二乗和 パラメータ数と同じ
input:γ (lr),θ (params),f(θ) (objective)τ (initial accumulator value),η (lr decay)initialize:state_sum0τ,θ0initial valuefort=1todogtθft(θt1)γ~γ1+(t1)ηstate_sumtstate_sumt1+gt2θtθt1γ~gtstate_sumt+ϵreturnθt \begin{aligned} %入力 &\rule{110mm}{0.4pt} \\ &\textbf{input} : \gamma \text{ (lr)}, \: \theta \text{ (params)}, \: f(\theta) \text{ (objective)} \\ &\hspace{15mm} \tau \text{ (initial accumulator value)}, \: \eta\text{ (lr decay)}\\ %初期化 &\textbf{initialize} : state\_sum_0 \leftarrow \tau, \theta_0 \leftarrow \text{initial value} \\ %アルゴリズム &\rule{110mm}{0.4pt} \\ &\textbf{for} \: t=1 \: \textbf{to} \: \ldots \: \textbf{do} \\ &\hspace{5mm} g_t \leftarrow \nabla_{\theta} f_t (\theta_{t – 1}) \\ &\hspace{5mm} \tilde{\gamma} \leftarrow \frac{\gamma}{1 + (t – 1) \eta} \\ &\hspace{5mm} state\_sum_t \leftarrow state\_sum_{t – 1} + g^2_t \\ &\hspace{5mm} \theta_t \leftarrow \theta_{t – 1} – \tilde{\gamma} \frac{g_t}{\sqrt{state\_sum_t}+\epsilon} \\ &\rule{110mm}{0.4pt} \\ &\bf{return} \: \theta_t \\ &\rule{110mm}{0.4pt} \\ \end{aligned}

学習率の減衰率が η>0\eta > 0 の場合、学習率はステップごとに減衰します。

γ~γ1+(t1)η \tilde{\gamma} \leftarrow \frac{\gamma}{1 + (t – 1) \eta}

state_sumtstate\_sum_t は勾配の二乗のステップ tt までの総和です。勾配の大きさを記録するのが目的のため、二乗をとっています。

state_sumt=state_sumt1+gt2=i=0tgt2 state\_sum_t = state\_sum_{t-1} + g^2_t = \sum_{i = 0}^t g^2_t

γ~\tilde{\gamma}state_sumt\sqrt{state\_sum_t} で割ることで学習率を調整します。序盤は state_sumtstate\_sum_t が小さいため調整後の学習率は大きくなり、終盤は state_sumtstate\_sum_t が大きいため調整後の学習率は小さくなります。ϵ\epsilonstate_sumtstate\_sum_t の値が小さい序盤に、除算結果が大きくなりすぎないように調整するための係数です。

θtθt1gtγ~state_sumt+ϵ \theta_t \leftarrow \theta_{t – 1} – g_t \frac{\tilde{\gamma}}{\sqrt{state\_sum_t} + \epsilon}

AdaGrad の欠点として、序盤の勾配が大きい場合に、学習が途中の段階で、調整後の学習率が小さくなってしまい、パラメータがほとんど更新されなくなることがあります。

以下は f(x,y)=0.1x2+y2f(x, y) = 0.1 * x^2 + y^2 という関数を lr=1.0 の AdaGrad で最適化した結果になります。

以下は state_dictstate\_dict の値の推移です。x2x_2 方向は序盤の勾配が急のため、state_dictstate\_dict の値が急に大きくなっています。

以下は調整後の学習率の値の推移です。x2x_2 方向の state_dictstate\_dict に応じて学習率が調整されていることがわかります。

RMSprop、RMSpropGraves

AdaGrad では、勾配の二乗のステップ tt までの総和を計算し、その平方根で除算していたため、過去の勾配の大きさはすべて等しく学習率の調整に影響を与えていました。一方、RMSprop では、勾配の二乗のステップ tt までの指数移動平均を計算します。指数移動平均のため、直近のステップの勾配の大きさがより重視されるようになります。

torch.optim.RMSprop(params, lr=0.01, alpha=0.99, eps=1e-08, weight_decay=0, momentum=0, centered=False)
Python
パラメータ 意味 初期値 範囲
lr 学習率 0.01 0以上の小数
alpha 指数移動平均の係数 0.99 0以上の小数
eps epsilon 1e-8 0以上の小数
weight_decay weight decay の係数 0 0以上の小数
momentum Momentum の係数 0 0以上の小数
centered centered RMSProp を有効にするかどうか FALSE bool

Optimizer の状態

パラメータ 意味 サイズ
momentum_buffer Momentum のバッファ パラメータ数と同じ
square_avg 勾配の二乗の指数移動平均 パラメータ数と同じ
input:α (alpha),γ (lr),θ (params),f(θ) (objective)μ (momentum)initialize:v00 (square average),b00 (buffer),θ0initial valuefort=1todogtθft(θt1)vtαvt1+(1α)gt2ifμ>0btμbt1+gtvt+ϵθtθt1γbtelseθtθt1γgtvt+ϵreturnθt \begin{aligned} %入力 &\rule{110mm}{0.4pt} \\ &\textbf{input} : \alpha \text{ (alpha)}, \: \gamma \text{ (lr)}, \: \theta \text{ (params)}, \: f(\theta) \text{ (objective)} \\ &\hspace{15mm} \mu \text{ (momentum)} \\ %初期化 &\textbf{initialize} : v_0 \leftarrow 0 \text{ (square average)}, \: \textbf{b}_0 \leftarrow 0 \text{ (buffer)}, \: \theta_0 \leftarrow \text{initial value} \\ %アルゴリズム &\rule{110mm}{0.4pt} \\ &\textbf{for} \: t=1 \: \textbf{to} \: \ldots \: \textbf{do} \\ &\hspace{5mm}g_t \leftarrow \nabla_{\theta} f_t (\theta_{t – 1}) \\ &\hspace{5mm}v_t \leftarrow \alpha v_{t – 1} + (1 – \alpha) g^2_t \\ &\hspace{5mm}if \: \mu > 0 \\ &\hspace{10mm} \textbf{b}_t\leftarrow \mu \textbf{b}_{t-1} + \frac{g_t}{\sqrt{v_t} + \epsilon} \\ &\hspace{10mm} \theta_t \leftarrow \theta_{t – 1} – \gamma \textbf{b}_t \\ &\hspace{5mm} else \\ &\hspace{10mm}\theta_t \leftarrow \theta_{t – 1} – \gamma \frac{g_t}{\sqrt{v_t} + \epsilon} \hspace{3mm} \\ %出力 &\rule{110mm}{0.4pt} \\ &\bf{return} \: \theta_t \\ &\rule{110mm}{0.4pt} \\ \end{aligned}

勾配の二乗の指数移動平均をとります。α\alpha の値が小さいほど過去の勾配の影響が弱くなります。

vtαvt1+(1α)gt2 v_t \leftarrow \alpha v_{t-1} + (1 – \alpha) g^2_t

以下は f(x,y)=0.1x2+y2f(x, y) = 0.1 * x^2 + y^2 という関数を lr=0.1, alpha=0.9 の RMSprop で最適化した結果になります。

以下は vtv_t の値の推移です。移動指数平均なので、序盤の勾配が急なところで大きくなったあと、徐々に小さくなっているのがわかります。

以下は調整後の学習率の値の推移です。vtv_t の値に応じて学習率が調整されていることがわかります。

RMSpropGraves

centerd=True の場合、RMSpropGraves という RMSProp の改良版になります。RMSprop との違いは、勾配の二乗の指数移動平均から勾配の指数移動平均を減算するように変更されている点です。

Optimizer の状態

パラメータ 意味 サイズ
momentum_buffer Momentum のバッファ パラメータ数と同じ
grad_avg 勾配の指数移動平均 パラメータ数と同じ
square_avg 勾配の二乗の指数移動平均 パラメータ数と同じ
input:α (alpha),γ (lr),θ (params),f(θ) (objective)λ (weight decay),μ (momentum)initialize:v00 (square average),b00 (buffer),g0ave0,θ0initial valuefort=1todogtθft(θt1)vtαvt1+(1α)gt2gtaveαgt1ave+(1α)gtvt~vt~(gtave)2ifμ>0btμbt1+gtvt~+ϵθtθt1γbtelseθtθt1γgtvt~+ϵreturnθt \begin{aligned} %入力 &\rule{110mm}{0.4pt} \\ &\textbf{input} : \alpha \text{ (alpha)}, \: \gamma \text{ (lr)}, \: \theta \text{ (params)}, \: f(\theta) \text{ (objective)} \\ &\hspace{15mm} \lambda \text{ (weight decay)}, \: \mu \text{ (momentum)} \\ %初期化 &\textbf{initialize} : v_0 \leftarrow 0 \text{ (square average)}, \: \textbf{b}_0 \leftarrow 0 \text{ (buffer)}, \: g^{ave}_0 \leftarrow 0, \: \\ &\hspace{20mm} \theta_0 \leftarrow \text{initial value} \\ %アルゴリズム &\rule{110mm}{0.4pt} \\ &\textbf{for} \: t=1 \: \textbf{to} \: \ldots \: \textbf{do} \\ &\hspace{5mm}g_t \leftarrow \nabla_{\theta} f_t (\theta_{t – 1}) \\ &\hspace{5mm}v_t \leftarrow \alpha v_{t – 1} + (1 – \alpha) g^2_t \\ &\hspace{5mm} g^{ave}_t \leftarrow \alpha g^{ave}_{t – 1} + (1 – \alpha) g_t \\ &\hspace{5mm} \tilde{v_t} \leftarrow \tilde{v_t} – \big(g^{ave}_{t} \big)^2 \\ &\hspace{5mm}if \: \mu > 0 \\ &\hspace{10mm} \textbf{b}_t\leftarrow \mu \textbf{b}_{t – 1} + \frac{g_t}{\sqrt{\tilde{v_t}} + \epsilon} \\ &\hspace{10mm} \theta_t \leftarrow \theta_{t – 1} – \gamma \textbf{b}_t \\ &\hspace{5mm} else \\ &\hspace{10mm}\theta_t \leftarrow \theta_{t – 1} – \gamma \frac{g_t}{\sqrt{\tilde{v_t}} + \epsilon} \hspace{3mm} \\ %出力 &\rule{110mm}{0.4pt} \\ &\bf{return} \: \theta_t \\ &\rule{110mm}{0.4pt} \\ \end{aligned}

Adadelta

Adadelta は AdaGrad の以下の欠点を改善したアルゴリズムです。

  1. 学習途中で学習率が小さくなってしまう
  2. ベースの学習率を設定する必要がある
torch.optim.Adadelta(params, lr=1.0, rho=0.9, eps=1e-06, weight_decay=0)
Python

Adadelta の論文に記載されているアルゴリズムでは、学習率は存在しませんが、Pytorch では API の便宜上、Adadelta によって決定された学習率にスケールするためのパラメータとして lr が残っています。lr=1 とすれば、論文と同じアルゴリズムになります。

パラメータ 意味 初期値 範囲
lr 学習率 1.0 0以上の小数
rho 移動指数平均の係数 0.9 0以上の小数
eps epsilon 1e-6 0以上の小数
weight_decay weight decay の係数 0 0以上の小数

Optimizer の状態

パラメータ 意味 サイズ
square_avg 勾配の二乗の指数移動平均 パラメータ数と同じ
acc_delta 更新量の移動指数平均 パラメータ数と同じ
input:γ (lr),θ (params),f(θ) (objective),ρ (decay)initialize:v00 (square avg),u00 (accumulate variables),θ0initial valuefort=1todogtθft(θt1)vtρvt1+(1ρ)gt2Δxtut1+ϵvt+ϵgtutρut1+(1ρ)Δxt2θtθt1γΔxtreturnθt \begin{aligned} %入力 &\rule{110mm}{0.4pt} \\ &\textbf{input} : \gamma \text{ (lr)}, \: \theta \text{ (params)}, \: f(\theta) \text{ (objective)}, \: \rho \text{ (decay)} \\ %初期化 &\textbf{initialize} : v_0 \leftarrow 0 \: \text{ (square avg)}, \: u_0 \leftarrow 0 \: \text{ (accumulate variables)}, \: \theta_0 \leftarrow \text{initial value} \\ %アルゴリズム &\rule{110mm}{0.4pt} \\ &\textbf{for} \: t=1 \: \textbf{to} \: \ldots \: \textbf{do} \\ &\hspace{5mm} g_t \leftarrow \nabla_{\theta} f_t (\theta_{t – 1}) \\ &\hspace{5mm} v_t \leftarrow \rho v_{t – 1} + (1 – \rho) g^2_t \\ &\hspace{5mm} \Delta x_t \leftarrow \frac{\sqrt{u_{t – 1} + \epsilon }}{ \sqrt{v_t + \epsilon} }g_t \\ &\hspace{5mm} u_t \leftarrow \rho u_{t – 1} + (1 – \rho) \Delta x^2_t \\ &\hspace{5mm}\theta_t \leftarrow \theta_{t – 1} – \gamma \Delta x_t \\ &\rule{110mm}{0.4pt} \\ &\bf{return} \: \theta_t \\ &\rule{110mm}{0.4pt} \\ \end{aligned}

学習途中で学習率が小さくなってしまう問題に関しては、RMSProp 同様、勾配の二乗和ではなく、勾配の移動指数平均を計算するように変更することで対策しました。

vtρvt1+(1ρ)gt2 v_t \leftarrow \rho v_{t – 1} + (1 – \rho) g^2_t

分母の ut1+ϵ\sqrt{u_{t – 1} + \epsilon} は更新量の単位をパラメータと合わせて、学習率の設定を不要にするためについています。 パラメータがそれぞれ仮想の単位を持っていると仮定したとき、パラメータの変化量はパラメータの単位に合わせて行われるべきです。 次元解析の考え方を取り入れて、SGD や AdaGrad、RMSprop の更新式を考察してみます。

SGD の次元解析

θtθt1γθft(θt1) \theta_t \leftarrow \theta_{t – 1} – \gamma \nabla_{\theta} f_t (\theta_{t – 1}) \\

Δθt=θtθt1\Delta \theta_t = \theta_t – \theta_{t – 1} とし、ff の単位は無次元量であると仮定したとき、(units of θf(θ))=1(units of θ)(\text{units of } \nabla_{\theta} f (\theta)) = \frac{1}{(\text{units of } \theta)} であるから、

(units of Δθ)=(units of γθf(θ))=(units of γ)(units of θ) (\text{units of } \Delta \theta) = \big(\text{units of } \gamma \nabla_{\theta} f (\theta) \big) = \frac{(\text{units of } \gamma)}{(\text{units of } \theta)}

パラメータの更新量の単位 (units of Δθ)(\text{units of } \Delta \theta) をパラメータの単位 (units of θ)(\text{units of } \theta) に合わせるには、学習率の単位を

(units of γ)=(units of θ)2 (\text{units of } \gamma) = (\text{units of } \theta)^2

として単位を調整する必要があります。

AdaGrad、RMSprop の次元解析

gtθft(θt1)γ~γ1+(t1)ηstate_sumtstate_sumt1+gt2θtθt1γ~gtstate_sumt+ϵ \begin{aligned} &g_t \leftarrow \nabla_{\theta} f_t (\theta_{t – 1}) \\ &\tilde{\gamma} \leftarrow \frac{\gamma}{1 + (t – 1) \eta} \\ &state\_sum_t \leftarrow state\_sum_{t – 1} + g^2_t \\ &\theta_t \leftarrow \theta_{t – 1} – \tilde{\gamma} \frac{g_t}{\sqrt{state\_sum_t}+\epsilon} \\ \end{aligned}

Δθt=θtθt1\Delta \theta_t = \theta_t – \theta_{t – 1} とし、f,ϵ,ηf, \epsilon, \eta の単位は無次元量であると仮定したとき、(units of state_sum)=1(units of θ)2(\text{units of } state\_sum) = \frac{1}{(\text{units of } \theta)^2} であるから、

(units of Δθ)=(units of γ~)1(units of θ)(units of θ) (\text{units of } \Delta \theta) = (\text{units of } \tilde{\gamma}) \frac{1}{(\text{units of } \theta)} (\text{units of } \theta)

パラメータの更新量の単位 (units of Δθ)(\text{units of } \Delta \theta) をパラメータの単位 (units of θ)(\text{units of } \theta) に合わせるには、学習率の単位を

(units of γ)=(units of θ) (\text{units of } \gamma) = (\text{units of } \theta)

として単位を調整する必要があります。RMSprop の vv も勾配の二乗の指数移動平均なので、AdaGrad と同じです。

ニュートン法の次元解析を元にした AdaDelta の単位合わせ

ニュートン法の更新量は

Δθ=H1θf(θ) \Delta \theta = – H^{-1} \nabla_\theta f(\theta)

です。ただし、HH はヘッセ行列を表します。 次元解析を行うと、ff の単位は無次元量であると仮定したとき、

(units of Δθ)=(units of H1)(units of θf(θ))(units of H1)=(units of Δθ)(units of θf(θ)) \begin{aligned} (\text{units of } \Delta \theta) &= (\text{units of } H^{-1}) (\text{units of } \nabla_\theta f(\theta)) \\ (\text{units of } H^{-1}) &= \frac{(\text{units of } \Delta \theta)}{(\text{units of } \nabla_\theta f(\theta))} \end{aligned}

これをニュートン法の更新量の式に代入して、

(units of Δθ)=(units of Δθ)(units of θf(θ))(units of θf(θ)) (\text{units of } \Delta \theta) = \frac{(\text{units of } \Delta \theta)}{(\text{units of } \nabla_\theta f(\theta))} (\text{units of } \nabla_\theta f(\theta))

Adadelta では、分子に単位を揃えるために Δθ\Delta \theta の二乗のステップ tt までの二乗の移動指数平均 utu_t を計算し、その値を分母に追加しています。

Δxtut1+ϵvt+ϵgt \Delta x_t \leftarrow \frac{\sqrt{u_{t – 1} + \epsilon }}{ \sqrt{v_t + \epsilon} }g_t

しかし、Δxt\Delta x_t を計算する段階では、utu_t はまだわからないので、代わりに Δxt\Delta x_t は滑らかに変化するという仮定をおいて、1つ前のステップの ut1u_{t – 1} で近似します。Δxt\Delta x_t が計算できたら、移動指数平均 utu_t を更新します。

utρut1+(1ρ)Δxt2 u_t \leftarrow \rho u_{t – 1} + (1 – \rho) \Delta x^2_t

AdaDelta の次元解析

gtθft(θt1)vtρvt1+(1ρ)gt2Δxtut1+ϵvt+ϵgtutρut1+(1ρ)Δxt2θtθt1γΔxt \begin{aligned} &g_t \leftarrow \nabla_{\theta} f_t (\theta_{t – 1}) \\ &v_t \leftarrow \rho v_{t – 1} + (1 – \rho) g^2_t \\ &\Delta x_t \leftarrow \frac{\sqrt{u_{t – 1} + \epsilon }}{ \sqrt{v_t + \epsilon} }g_t \\ &u_t \leftarrow \rho u_{t – 1} + (1 – \rho) \Delta x^2_t \\ &\theta_t \leftarrow \theta_{t – 1} – \gamma \Delta x_t \\ \end{aligned}

Δθt=θtθt1\Delta \theta_t = \theta_t – \theta_{t – 1} とし、f,ϵ,ρ,γf, \epsilon, \rho, \gamma の単位は無次元量であると仮定したとき、

(units of v)=1(units of θ)2(units of u)=(units of Δθ)2 \begin{aligned} (\text{units of } v) &= \frac{1}{(\text{units of } \theta)^2} \\ (\text{units of } u) &= (\text{units of } \Delta \theta)^2 \end{aligned}

であるから、

(units of Δθ)=(units of u)(units of v)(units of g)=(units of Δθ)(units of θ)1(units of θ)=(units of Δθ) \begin{aligned} (\text{units of } \Delta \theta) &= \frac{\sqrt{(\text{units of } u)}}{ \sqrt{(\text{units of } v)} } (\text{units of } g) \\ &= (\text{units of } \Delta \theta) (\text{units of } \theta) \frac{1}{(\text{units of } \theta)} \\ &= (\text{units of } \Delta \theta) \end{aligned}

AdaDelta の更新式は左辺と右辺の単位が一致しているため、学習率で単位を調整する必要がありません。

以下は f(x,y)=0.1x2+y2f(x, y) = 0.1 * x^2 + y^2 という関数を eps=1e-3 の Adadelta で最適化した結果になります。序盤で学習率が小さくなりすぎて更新されないのを防ぐ目的でデフォルト値より大きめの値を設定しました。

以下は vt,utv_t, u_t の値の推移です。移動指数平均なので、序盤の勾配が急なところで大きくなったあと、徐々に小さくなっているのがわかります。

以下は調整後の学習率の値の推移です。vt,utv_t, u_t の値に応じて学習率が調整されていることがわかります。

参考

コメント

コメントする