.. _sec_rmsprop:
RMSProp
=======
:numref:`sec_adagrad` içindeki en önemli konulardan biri, öğrenme
oranının önceden tanımlanmış bir zamanlamayla
:math:`\mathcal{O}(t^{-\frac{1}{2}})` etkin bir şekilde azalmasıdır. Bu
genellikle dışbükey problemler için uygun olsa da, derin öğrenmede
karşılaşılanlar gibi dışbükey olmayan olanlar için ideal olmayabilir.
Yine de, Adagrad'ın koordinat yönlü uyarlanması ön koşul olarak son
derece arzu edilir.
:cite:`Tieleman.Hinton.2012`, oran zamanlamasını koordinat-uyarlamalı
öğrenme oranlarından ayırmak için basit bir düzeltme olarak RMSProp
algoritmasını önerdi. Sorun, Adagrad'ın :math:`\mathbf{g}_t` gradyanının
karelerini bir durum vektörü
:math:`\mathbf{s}_t = \mathbf{s}_{t-1} + \mathbf{g}_t^2` olarak
biriktirmesidir. Sonuç olarak :math:`\mathbf{s}_t`, normalleştirme
eksikliğinden dolayı sınır olmadan, esasında algoritma yakınsadıkça
doğrusal olarak büyümeye devam eder.
Bu sorunu çözmenin bir yolu :math:`\mathbf{s}_t / t`'yi kullanmaktır.
:math:`\mathbf{g}_t`'nin makul dağılımları için bu yakınsayacaktır. Ne
yazık ki, prosedür tüm değerlerin yörüngesini hatırladığından, limit
davranışının etkin olmaya başlaması çok uzun zaman alabilir.
Alternatifi, momentum yönteminde kullandığımız gibi sızan bir ortalama
kullanmaktır, yani bazı :math:`\gamma > 0` parametresi için
:math:`\mathbf{s}_t \leftarrow \gamma \mathbf{s}_{t-1} + (1-\gamma) \mathbf{g}_t^2`.
Diğer tüm parçaları değiştirmeden tutmak, RMSProp'u verir.
Algoritma
---------
Denklemleri ayrıntılı olarak yazalım.
.. math::
\begin{aligned}
\mathbf{s}_t & \leftarrow \gamma \mathbf{s}_{t-1} + (1 - \gamma) \mathbf{g}_t^2, \\
\mathbf{x}_t & \leftarrow \mathbf{x}_{t-1} - \frac{\eta}{\sqrt{\mathbf{s}_t + \epsilon}} \odot \mathbf{g}_t.
\end{aligned}
:math:`\epsilon > 0` sabiti, sıfır veya aşırı büyük adım boyutlarına
bölünmediğimizden emin olmak için tipik olarak :math:`10^{-6}` olarak
ayarlanır. Bu genişleme göz önüne alındığında, koordinat başına
uygulanan ölçeklendirmeden bağımsız olarak :math:`\eta` öğrenme oranını
kontrol etmede serbestiz. Sızdıran ortalamalar açısından, momentum
yöntemi için daha önce uygulanan mantığın aynısını uygulayabiliriz.
:math:`\mathbf{s}_t` tanımını genişletmek şu ifadeye yol açar:
.. math::
\begin{aligned}
\mathbf{s}_t & = (1 - \gamma) \mathbf{g}_t^2 + \gamma \mathbf{s}_{t-1} \\
& = (1 - \gamma) \left(\mathbf{g}_t^2 + \gamma \mathbf{g}_{t-1}^2 + \gamma^2 \mathbf{g}_{t-2} + \ldots, \right).
\end{aligned}
Daha önce :numref:`sec_momentum` içinde olduğu gibi
:math:`1 + \gamma + \gamma^2 + \ldots, = \frac{1}{1-\gamma}`
kullanıyoruz. Bu nedenle ağırlıkların toplamı :math:`\gamma^{-1}`'lik
bir gözlem yarılanma ömrü ile :math:`1`'e normalleştirilir. Çeşitli
:math:`\gamma` seçenekleri için son 40 zaman adımının ağırlıklarını
görselleştirelim.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
%matplotlib inline
import math
from d2l import mxnet as d2l
from mxnet import np, npx
npx.set_np()
d2l.set_figsize()
gammas = [0.95, 0.9, 0.8, 0.7]
for gamma in gammas:
x = np.arange(40).asnumpy()
d2l.plt.plot(x, (1-gamma) * gamma ** x, label=f'gamma = {gamma:.2f}')
d2l.plt.xlabel('time');
.. figure:: output_rmsprop_251805_3_0.svg
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
import math
import torch
from d2l import torch as d2l
d2l.set_figsize()
gammas = [0.95, 0.9, 0.8, 0.7]
for gamma in gammas:
x = torch.arange(40).detach().numpy()
d2l.plt.plot(x, (1-gamma) * gamma ** x, label=f'gamma = {gamma:.2f}')
d2l.plt.xlabel('time');
.. figure:: output_rmsprop_251805_6_0.svg
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
import math
import tensorflow as tf
from d2l import tensorflow as d2l
d2l.set_figsize()
gammas = [0.95, 0.9, 0.8, 0.7]
for gamma in gammas:
x = tf.range(40).numpy()
d2l.plt.plot(x, (1-gamma) * gamma ** x, label=f'gamma = {gamma:.2f}')
d2l.plt.xlabel('time');
.. figure:: output_rmsprop_251805_9_0.svg
.. raw:: html
.. raw:: html
Sıfırdan Uygulama
-----------------
Daha önce olduğu gibi, RMSProp yörüngesini gözlemlemek için
:math:`f(\mathbf{x})=0.1x_1^2+2x_2^2` ikinci dereceden polinom işlevini
kullanıyoruz. :numref:`sec_adagrad` içinde Adagrad'ı 0.4 öğrenme
oranıyla kullandığımızda, öğrenme oranı çok hızlı düştüğü için
değişkenlerin algoritmanın sonraki aşamalarında çok yavaş hareket
ettiğini hatırlayın. :math:`\eta` ayrı ayrı kontrol edildiğinden bu
RMSProp ile gerçekleşmez.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
def rmsprop_2d(x1, x2, s1, s2):
g1, g2, eps = 0.2 * x1, 4 * x2, 1e-6
s1 = gamma * s1 + (1 - gamma) * g1 ** 2
s2 = gamma * s2 + (1 - gamma) * g2 ** 2
x1 -= eta / math.sqrt(s1 + eps) * g1
x2 -= eta / math.sqrt(s2 + eps) * g2
return x1, x2, s1, s2
def f_2d(x1, x2):
return 0.1 * x1 ** 2 + 2 * x2 ** 2
eta, gamma = 0.4, 0.9
d2l.show_trace_2d(f_2d, d2l.train_2d(rmsprop_2d))
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
epoch 20, x1: -0.010599, x2: 0.000000
.. figure:: output_rmsprop_251805_15_1.svg
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
def rmsprop_2d(x1, x2, s1, s2):
g1, g2, eps = 0.2 * x1, 4 * x2, 1e-6
s1 = gamma * s1 + (1 - gamma) * g1 ** 2
s2 = gamma * s2 + (1 - gamma) * g2 ** 2
x1 -= eta / math.sqrt(s1 + eps) * g1
x2 -= eta / math.sqrt(s2 + eps) * g2
return x1, x2, s1, s2
def f_2d(x1, x2):
return 0.1 * x1 ** 2 + 2 * x2 ** 2
eta, gamma = 0.4, 0.9
d2l.show_trace_2d(f_2d, d2l.train_2d(rmsprop_2d))
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
epoch 20, x1: -0.010599, x2: 0.000000
/home/d2l-worker/miniconda3/envs/d2l-tr-release-0/lib/python3.9/site-packages/torch/functional.py:478: UserWarning: torch.meshgrid: in an upcoming release, it will be required to pass the indexing argument. (Triggered internally at ../aten/src/ATen/native/TensorShape.cpp:2895.)
return _VF.meshgrid(tensors, **kwargs) # type: ignore[attr-defined]
.. figure:: output_rmsprop_251805_18_1.svg
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
def rmsprop_2d(x1, x2, s1, s2):
g1, g2, eps = 0.2 * x1, 4 * x2, 1e-6
s1 = gamma * s1 + (1 - gamma) * g1 ** 2
s2 = gamma * s2 + (1 - gamma) * g2 ** 2
x1 -= eta / math.sqrt(s1 + eps) * g1
x2 -= eta / math.sqrt(s2 + eps) * g2
return x1, x2, s1, s2
def f_2d(x1, x2):
return 0.1 * x1 ** 2 + 2 * x2 ** 2
eta, gamma = 0.4, 0.9
d2l.show_trace_2d(f_2d, d2l.train_2d(rmsprop_2d))
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
epoch 20, x1: -0.010599, x2: 0.000000
.. figure:: output_rmsprop_251805_21_1.svg
.. raw:: html
.. raw:: html
Ardından, derin bir ağda kullanılacak RMSProp'u uyguluyoruz. Bu da son
derece basit.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
def init_rmsprop_states(feature_dim):
s_w = np.zeros((feature_dim, 1))
s_b = np.zeros(1)
return (s_w, s_b)
def rmsprop(params, states, hyperparams):
gamma, eps = hyperparams['gamma'], 1e-6
for p, s in zip(params, states):
s[:] = gamma * s + (1 - gamma) * np.square(p.grad)
p[:] -= hyperparams['lr'] * p.grad / np.sqrt(s + eps)
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
def init_rmsprop_states(feature_dim):
s_w = torch.zeros((feature_dim, 1))
s_b = torch.zeros(1)
return (s_w, s_b)
def rmsprop(params, states, hyperparams):
gamma, eps = hyperparams['gamma'], 1e-6
for p, s in zip(params, states):
with torch.no_grad():
s[:] = gamma * s + (1 - gamma) * torch.square(p.grad)
p[:] -= hyperparams['lr'] * p.grad / torch.sqrt(s + eps)
p.grad.data.zero_()
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
def init_rmsprop_states(feature_dim):
s_w = tf.Variable(tf.zeros((feature_dim, 1)))
s_b = tf.Variable(tf.zeros(1))
return (s_w, s_b)
def rmsprop(params, grads, states, hyperparams):
gamma, eps = hyperparams['gamma'], 1e-6
for p, s, g in zip(params, states, grads):
s[:].assign(gamma * s + (1 - gamma) * tf.math.square(g))
p[:].assign(p - hyperparams['lr'] * g / tf.math.sqrt(s + eps))
.. raw:: html
.. raw:: html
İlk öğrenme oranını 0.01 ve ağırlıklandırma terimi :math:`\gamma`'yı
0.9'a ayarladık. Yani, :math:`\mathbf{s}`, kare gradyanın son
:math:`1/(1-\gamma) = 10` adet gözlem üzerinden ortalama olarak
toplanır.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
data_iter, feature_dim = d2l.get_data_ch11(batch_size=10)
d2l.train_ch11(rmsprop, init_rmsprop_states(feature_dim),
{'lr': 0.01, 'gamma': 0.9}, data_iter, feature_dim);
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
loss: 0.245, 0.159 sec/epoch
.. figure:: output_rmsprop_251805_39_1.svg
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
data_iter, feature_dim = d2l.get_data_ch11(batch_size=10)
d2l.train_ch11(rmsprop, init_rmsprop_states(feature_dim),
{'lr': 0.01, 'gamma': 0.9}, data_iter, feature_dim);
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
loss: 0.250, 0.015 sec/epoch
.. figure:: output_rmsprop_251805_42_1.svg
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
data_iter, feature_dim = d2l.get_data_ch11(batch_size=10)
d2l.train_ch11(rmsprop, init_rmsprop_states(feature_dim),
{'lr': 0.01, 'gamma': 0.9}, data_iter, feature_dim);
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
loss: 0.244, 0.115 sec/epoch
.. figure:: output_rmsprop_251805_45_1.svg
.. raw:: html
.. raw:: html
Kısa Uygulama
-------------
RMSProp oldukça popüler bir algoritma olduğundan ``Trainer`` örneğinde
de mevcuttur. Tek yapmamız gereken ``rmsprop`` adlı bir algoritma
kullanarak, :math:`\gamma`'yı ``gamma1`` parametresine atamak.
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
d2l.train_concise_ch11('rmsprop', {'learning_rate': 0.01, 'gamma1': 0.9},
data_iter)
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
loss: 0.245, 0.089 sec/epoch
.. figure:: output_rmsprop_251805_51_1.svg
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
trainer = torch.optim.RMSprop
d2l.train_concise_ch11(trainer, {'lr': 0.01, 'alpha': 0.9},
data_iter)
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
loss: 0.242, 0.014 sec/epoch
.. figure:: output_rmsprop_251805_54_1.svg
.. raw:: html
.. raw:: html
.. raw:: latex
\diilbookstyleinputcell
.. code:: python
trainer = tf.keras.optimizers.RMSprop
d2l.train_concise_ch11(trainer, {'learning_rate': 0.01, 'rho': 0.9},
data_iter)
.. raw:: latex
\diilbookstyleoutputcell
.. parsed-literal::
:class: output
loss: 0.248, 0.141 sec/epoch
.. figure:: output_rmsprop_251805_57_1.svg
.. raw:: html
.. raw:: html
Özet
----
- RMSProp, her ikisi de katsayıları ölçeklendirmek için gradyanın
karesini kullandığı için Adagrad'a çok benzer.
- RMSProp, sızıntı ortalamasını momentum ile paylaşır. Bununla
birlikte, RMSProp, katsayı bazında ön koşullayıcıyı ayarlamak için bu
tekniği kullanır.
- Öğrenme oranının pratikte deney yapan tarafından planlanması gerekir.
- :math:`\gamma` katsayısı, koordinat başına ölçeği ayarlarken geçmişin
ne kadar geri gideceğini belirler.
Alıştırmalar
------------
1. :math:`\gamma = 1`'i ayarlarsak deneysel olarak ne olur? Neden?
2. Optimizasyon problemi
:math:`f(\mathbf{x}) = 0.1 (x_1 + x_2)^2 + 2 (x_1 - x_2)^2`'yi en aza
indirmek için döndürün. Yakınsamaya ne olur?
3. Fashion-MNIST eğitimi gibi gerçek bir makine öğrenmesi probleminde
RMSProp'a ne olduğunu deneyin. Öğrenme oranını ayarlamak için farklı
seçeneklerle denemeler yapın.
4. Optimizasyon ilerledikçe :math:`\gamma`'yı ayarlamak ister misiniz?
RMSProp buna ne kadar duyarlıdır?
.. raw:: html
.. raw:: html
`Tartışmalar `__
.. raw:: html
.. raw:: html
`Tartışmalar `__
.. raw:: html
.. raw:: html
`Tartışmalar `__
.. raw:: html
.. raw:: html