.. _sec_adadelta:
Adadelta
========
Adadelta là một biến thể khác của AdaGrad (:numref:`sec_adagrad`). Sự
khác biệt chính nằm ở thực tế là nó làm giảm số tiền mà tốc độ học tập
thích ứng với tọa độ. Hơn nữa, theo truyền thống, nó được gọi là không
có tỷ lệ học tập vì nó sử dụng số lượng thay đổi chính nó làm hiệu chuẩn
cho sự thay đổi trong tương lai. Thuật toán được đề xuất vào năm
:cite:`Zeiler.2012`. Nó khá đơn giản, được thảo luận về các thuật toán
trước đó cho đến nay.
Các thuật toán
--------------
Tóm lại, Adadelta sử dụng hai biến trạng thái, :math:`\mathbf{s}_t` để
lưu trữ trung bình bị rò rỉ của khoảnh khắc thứ hai của gradient và
:math:`\Delta\mathbf{x}_t` để lưu trữ trung bình bị rò rỉ của khoảnh
khắc thứ hai của sự thay đổi các tham số trong chính mô hình. Lưu ý rằng
chúng tôi sử dụng ký hiệu ban đầu và đặt tên của các tác giả để tương
thích với các ấn phẩm và triển khai khác (không có lý do thực sự nào
khác tại sao người ta nên sử dụng các biến Hy Lạp khác nhau để chỉ ra
một tham số phục vụ cùng một mục đích trong đà, Adagrad, RMSProp và
Adadelta).
Dưới đây là các chi tiết kỹ thuật của Adadelta. Với tham số du jour là
:math:`\rho`, chúng tôi có được các bản cập nhật rò rỉ sau tương tự như
:numref:`sec_rmsprop`:
.. math::
\begin{aligned}
\mathbf{s}_t & = \rho \mathbf{s}_{t-1} + (1 - \rho) \mathbf{g}_t^2.
\end{aligned}
Sự khác biệt đối với :numref:`sec_rmsprop` là chúng tôi thực hiện các
bản cập nhật với gradient :math:`\mathbf{g}_t'` được thay đổi lại, tức
là,
.. math::
\begin{aligned}
\mathbf{x}_t & = \mathbf{x}_{t-1} - \mathbf{g}_t'. \\
\end{aligned}
Vậy gradient được rescaled :math:`\mathbf{g}_t'` là gì? Chúng ta có thể
tính toán nó như sau:
.. math::
\begin{aligned}
\mathbf{g}_t' & = \frac{\sqrt{\Delta\mathbf{x}_{t-1} + \epsilon}}{\sqrt{{\mathbf{s}_t + \epsilon}}} \odot \mathbf{g}_t, \\
\end{aligned}
trong đó :math:`\Delta \mathbf{x}_{t-1}` là mức trung bình bị rò rỉ của
gradient được định lại bình phương :math:`\mathbf{g}_t'`. Chúng tôi khởi
tạo :math:`\Delta \mathbf{x}_{0}` là :math:`0` và cập nhật nó ở mỗi bước
với :math:`\mathbf{g}_t'`, tức là,
.. math::
\begin{aligned}
\Delta \mathbf{x}_t & = \rho \Delta\mathbf{x}_{t-1} + (1 - \rho) {\mathbf{g}_t'}^2,
\end{aligned}
và :math:`\epsilon` (một giá trị nhỏ như :math:`10^{-5}`) được thêm vào
để duy trì sự ổn định số.
Thực hiện
---------
Adadelta cần duy trì hai biến trạng thái cho mỗi biến,
:math:`\mathbf{s}_t` và :math:`\Delta\mathbf{x}_t`. Điều này mang lại
việc thực hiện sau đây.
.. raw:: html
.. raw:: html
.. code:: python
%matplotlib inline
from mxnet import np, npx
from d2l import mxnet as d2l
npx.set_np()
def init_adadelta_states(feature_dim):
s_w, s_b = np.zeros((feature_dim, 1)), np.zeros(1)
delta_w, delta_b = np.zeros((feature_dim, 1)), np.zeros(1)
return ((s_w, delta_w), (s_b, delta_b))
def adadelta(params, states, hyperparams):
rho, eps = hyperparams['rho'], 1e-5
for p, (s, delta) in zip(params, states):
# In-place updates via [:]
s[:] = rho * s + (1 - rho) * np.square(p.grad)
g = (np.sqrt(delta + eps) / np.sqrt(s + eps)) * p.grad
p[:] -= g
delta[:] = rho * delta + (1 - rho) * g * g
.. raw:: html
.. raw:: html
.. code:: python
%matplotlib inline
import torch
from d2l import torch as d2l
def init_adadelta_states(feature_dim):
s_w, s_b = torch.zeros((feature_dim, 1)), torch.zeros(1)
delta_w, delta_b = torch.zeros((feature_dim, 1)), torch.zeros(1)
return ((s_w, delta_w), (s_b, delta_b))
def adadelta(params, states, hyperparams):
rho, eps = hyperparams['rho'], 1e-5
for p, (s, delta) in zip(params, states):
with torch.no_grad():
# In-place updates via [:]
s[:] = rho * s + (1 - rho) * torch.square(p.grad)
g = (torch.sqrt(delta + eps) / torch.sqrt(s + eps)) * p.grad
p[:] -= g
delta[:] = rho * delta + (1 - rho) * g * g
p.grad.data.zero_()
.. raw:: html
.. raw:: html
.. code:: python
%matplotlib inline
import tensorflow as tf
from d2l import tensorflow as d2l
def init_adadelta_states(feature_dim):
s_w = tf.Variable(tf.zeros((feature_dim, 1)))
s_b = tf.Variable(tf.zeros(1))
delta_w = tf.Variable(tf.zeros((feature_dim, 1)))
delta_b = tf.Variable(tf.zeros(1))
return ((s_w, delta_w), (s_b, delta_b))
def adadelta(params, grads, states, hyperparams):
rho, eps = hyperparams['rho'], 1e-5
for p, (s, delta), grad in zip(params, states, grads):
s[:].assign(rho * s + (1 - rho) * tf.math.square(grad))
g = (tf.math.sqrt(delta + eps) / tf.math.sqrt(s + eps)) * grad
p[:].assign(p - g)
delta[:].assign(rho * delta + (1 - rho) * g * g)
.. raw:: html
.. raw:: html
Chọn :math:`\rho = 0.9` lên tới thời gian bán hủy là 10 cho mỗi bản cập
nhật tham số. Điều này có xu hướng hoạt động khá tốt. Chúng tôi nhận
được hành vi sau đây.
.. raw:: html
.. raw:: html
.. code:: python
data_iter, feature_dim = d2l.get_data_ch11(batch_size=10)
d2l.train_ch11(adadelta, init_adadelta_states(feature_dim),
{'rho': 0.9}, data_iter, feature_dim);
.. parsed-literal::
:class: output
loss: 0.244, 0.120 sec/epoch
.. figure:: output_adadelta_0b41cb_15_1.svg
.. raw:: html
.. raw:: html
.. code:: python
data_iter, feature_dim = d2l.get_data_ch11(batch_size=10)
d2l.train_ch11(adadelta, init_adadelta_states(feature_dim),
{'rho': 0.9}, data_iter, feature_dim);
.. parsed-literal::
:class: output
loss: 0.244, 0.016 sec/epoch
.. figure:: output_adadelta_0b41cb_18_1.svg
.. raw:: html
.. raw:: html
.. code:: python
data_iter, feature_dim = d2l.get_data_ch11(batch_size=10)
d2l.train_ch11(adadelta, init_adadelta_states(feature_dim),
{'rho': 0.9}, data_iter, feature_dim);
.. parsed-literal::
:class: output
loss: 0.243, 0.151 sec/epoch
.. figure:: output_adadelta_0b41cb_21_1.svg
.. raw:: html
.. raw:: html
Để thực hiện ngắn gọn, chúng tôi chỉ cần sử dụng thuật toán ``adadelta``
từ lớp ``Trainer``. Điều này mang lại một lớp lót sau đây cho một lời
gọi nhỏ gọn hơn nhiều.
.. raw:: html
.. raw:: html
.. code:: python
d2l.train_concise_ch11('adadelta', {'rho': 0.9}, data_iter)
.. parsed-literal::
:class: output
loss: 0.245, 0.120 sec/epoch
.. figure:: output_adadelta_0b41cb_27_1.svg
.. raw:: html
.. raw:: html
.. code:: python
trainer = torch.optim.Adadelta
d2l.train_concise_ch11(trainer, {'rho': 0.9}, data_iter)
.. parsed-literal::
:class: output
loss: 0.244, 0.015 sec/epoch
.. figure:: output_adadelta_0b41cb_30_1.svg
.. raw:: html
.. raw:: html
.. code:: python
# adadelta is not converging at default learning rate
# but it's converging at lr = 5.0
trainer = tf.keras.optimizers.Adadelta
d2l.train_concise_ch11(trainer, {'learning_rate':5.0, 'rho': 0.9}, data_iter)
.. parsed-literal::
:class: output
loss: 0.244, 0.105 sec/epoch
.. figure:: output_adadelta_0b41cb_33_1.svg
.. raw:: html
.. raw:: html
Tóm tắt
-------
- Adadelta không có tham số tỷ lệ học tập. Thay vào đó, nó sử dụng tốc
độ thay đổi trong chính các thông số để điều chỉnh tốc độ học tập.
- Adadelta yêu cầu hai biến trạng thái để lưu trữ những khoảnh khắc thứ
hai của gradient và sự thay đổi trong các tham số.
- Adadelta sử dụng trung bình rò rỉ để giữ ước tính chạy của các số
liệu thống kê thích hợp.
Bài tập
-------
1. Điều chỉnh giá trị của :math:`\rho`. Điều gì xảy ra?
2. Hiển thị cách thực hiện thuật toán mà không cần sử dụng
:math:`\mathbf{g}_t'`. Tại sao đây có thể là một ý tưởng tốt?
3. Adadelta có thực sự học tỷ lệ miễn phí không? Bạn có thể tìm thấy các
vấn đề tối ưu hóa phá vỡ Adadelta?
4. So sánh Adadelta với Adagrad và RMS prop để thảo luận về hành vi hội
tụ của họ.
.. raw:: html
.. raw:: html
`Discussions `__
.. raw:: html
.. raw:: html
`Discussions `__
.. raw:: html
.. raw:: html
`Discussions `__
.. raw:: html
.. raw:: html