.. _sec_adadelta: Adadelta ======== Adadelta — это ещё один вариант AdaGrad (:numref:`sec_adagrad`). Главное отличие заключается в том, что он уменьшает величину, на которую скорость обучения адаптируется к координатам. Кроме того, традиционно считается, что этот алгоритм не имеет скорости обучения, поскольку он использует величину изменения в качестве калибровки для будущих изменений. Алгоритм был предложен в работе :cite:t:`Zeiler.2012`. Он достаточно прост, учитывая обсуждение предыдущих алгоритмов. Алгоритм -------- Короче говоря, Adadelta использует две переменные состояния: :math:`\mathbf{s}_t` для хранения затухающего среднего второго момента градиента и :math:`\Delta\mathbf{x}_t` для хранения затухающего среднего второго момента изменения параметров в самой модели. Обратите внимание, что мы используем оригинальную нотацию и обозначения авторов для совместимости с другими публикациями и реализациями (нет никаких иных причин использовать разные греческие буквы для обозначения параметров, выполняющих одну и ту же функцию в импульсе, Adagrad, RMSProp и Adadelta). Ниже приведены технические детали алгоритма Adadelta. Если текущим параметром является :math:`\rho`, мы получаем следующие частичные обновления, аналогично :numref:`sec_rmsprop`: .. math:: \begin{aligned} \mathbf{s}_t & = \rho \mathbf{s}_{t-1} + (1 - \rho) \mathbf{g}_t^2. \end{aligned} Отличие от :numref:`sec_rmsprop` заключается в том, что мы выполняем обновления с помощью перемасштабированного градиента :math:`\mathbf{g}_t'`, то есть .. math:: \begin{aligned} \mathbf{x}_t & = \mathbf{x}_{t-1} - \mathbf{g}_t'. \\ \end{aligned} Так что же такое пересчитанный градиент :math:`\mathbf{g}_t'`? Мы можем вычислить его следующим образом: .. 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} где :math:`\Delta \mathbf{x}_{t-1}` — это затухающее среднее квадратов пересчитанных градиентов :math:`\mathbf{g}_t'`. Мы инициализируем :math:`\Delta \mathbf{x}_{0}` значением :math:`0` и обновляем его на каждом шаге с помощью :math:`\mathbf{g}_t'`, то есть .. math:: \begin{aligned} \Delta \mathbf{x}_t & = \rho \Delta\mathbf{x}_{t-1} + (1 - \rho) {\mathbf{g}_t'}^2, \end{aligned} и :math:`\epsilon` (небольшое значение, например, :math:`10^{-5}`) добавляется для обеспечения численной устойчивости. Реализация ---------- Adadelta требует хранения двух переменных состояния для каждой переменной, :math:`\mathbf{s}_t` и :math:`\Delta\mathbf{x}_t`. Это приводит к следующей реализации. .. raw:: latex \diilbookstyleinputcell .. 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_() Выбор :math:`\rho = 0.9` соответствует времени полураспада, равному 10, для каждого обновления параметра. Это обычно работает довольно хорошо. Мы получаем следующее поведение. .. raw:: latex \diilbookstyleinputcell .. 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); Для лаконичной реализации мы просто используем алгоритм Adadelta из высокоуровневых API. Это позволяет получить следующую однострочную запись, которая значительно компактнее. .. raw:: latex \diilbookstyleinputcell .. code:: python trainer = torch.optim.Adadelta d2l.train_concise_ch11(trainer, {'rho': 0.9}, data_iter) Итоги ----- - У Adadelta отсутствует параметр скорости обучения. Вместо этого он использует скорость изменения самих параметров для адаптации скорости обучения. - Adadelta требует две переменные состояния для хранения вторых моментов градиента и изменения параметров. - Adadelta использует затухающие средние для поддержания текущей оценки соответствующих статистик. Упражнения ---------- 1. Измените значение :math:`\rho`. Что произойдет? 2. Покажите, как реализовать алгоритм без использования :math:`\mathbf{g}_t'`. Почему это может быть хорошей идеей? 3. Действительно ли Adadelta не зависит от скорости обучения? Можете ли вы найти задачи оптимизации, в которых Adadelta дает сбой? 4. Сравните Adadelta с Adagrad и RMSprop, чтобы обсудить их поведение сходимости. `Обсуждения `__