.. _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
mxnetpytorchtensorflow
.. 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
mxnetpytorchtensorflow
.. 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
mxnetpytorchtensorflow
.. 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
mxnetpytorchtensorflow
.. raw:: html
`Discussions `__ .. raw:: html
.. raw:: html
`Discussions `__ .. raw:: html
.. raw:: html
`Discussions `__ .. raw:: html
.. raw:: html