Я не смог увидеть никакой информации об этом в Интернете, и связанная статья, конечно, не помогла, поэтому я посмотрел на модульные тесты для tf.train.MomentumOptimizer
, из которых я вижу тестыдля реализации как классического импульса, так и режимов NAG.
Сводка
var = var + accum * learning_rate * momentum
accum = accum * momentum + g
var = var - learning_rate * accum
var = var - accum * learning_rate * momentum
, где accum
начинается с 0 и обновляется на каждом шаге.Выше приведен модифицированный вариант формулировки в модульном тесте, и я нахожу его немного запутанным.Вот тот же набор уравнений, скомпонованный с моей интерпретацией того, что представляет каждый из параметров (хотя я могу ошибаться):
average_grad_0 = accum # previous rolling average
average_grad_1 = accum * momentum + g # updated rolling average
grad_diff = average_grad_1 - average_grad_0
adjustment = -learning_rate * (grad_diff * momentum + average_grad_1)
var += adjustment
accum = average_grad_new
Другими словами, мне кажется, что реализация tensorflow
мне кажетсяпытается угадать «скорректированный градиент» в NAG, предполагая, что новый градиент будет оцениваться текущим средним градиентом плюс произведение импульса и изменения среднего градиента.Я хотел бы увидеть доказательства этого!
Далее подробно рассказывается о том, как классические режимы и режимы нестеров реализованы в tensorflow
в соответствии с тестами.
Классический режим Momentum
Для use_nesterov=False
, основанного на функции doTestBasic
, у нас есть следующие начальные параметры:
learning_rate = 2.0
momentum = 0.9
var_0 = 1.0 # at time 0
grad = 0.1
На самом деле, это только первый элемент grads_0
и vars_0
массивов, но я сосредоточусь только на одном значении.Для последующих временных шагов у нас есть
var_1 = 1.0 - (0.1 * 2.0)
var_2 = 1.0 - (0.1 * 2.0) - ((0.9 * 0.1 + 0.1) * 2.0)
, который я собираюсь интерпретировать как значение;
var_1 = var_0 - (grad * learning_rate)
var_2 = var_1 - ((momentum * grad + grad) * learning_rate)
Если мы предположим, что для целей модульных тестов grad_0 == grad_1 == grad
тогдаэто имеет смысл как формулировка классического импульса.
Режим ускоренного градиента (NAG) Нестерова
Для use_nesterov=True
я посмотрел на функцию _update_nesterov_momentum_numpy
и тест testNesterovMomentum
case.
Функция _update_nesterov_momentum_numpy
имеет следующее определение:
def _update_nesterov_momentum_numpy(self, var, accum, g, lr, momentum):
var = var + accum * lr * momentum
accum = accum * momentum + g
var = var - lr * accum
var = var - accum * lr * momentum
return var, accum
и вызывается в модульных тестах следующим образом:
for t in range(1, 5):
opt_op.run()
var0_np, accum0_np = self._update_nesterov_momentum_numpy(
var0_np, accum0_np, var0_np * 10, 2.0, 0.9)