Тензорный поток: путаница в отношении оптимизатора adam
Я смущен относительно того, как оптимизатор adam работает в тензорном потоке.
Как я читал docs, он говорит, что скорость обучения меняется на каждую итерацию с градиентным спусками.
Но когда я вызываю функцию, я даю ей скорость обучения. И я не вызываю функцию, чтобы сказать, сделайте одну эпоху (неявно вызывая # итерации, чтобы пройти через обучение данным). Я вызываю функцию для каждой партии явно, как
for epoch in epochs
for batch in data
sess.run(train_adam_step, feed_dict={eta:1e-3})
Так что моя эта не может меняться. И я не передаю переменную времени. Или это какой-то тип типа генератора, где при создании сеанса t
увеличивается каждый раз, когда я вызываю оптимизатор?
Предполагая, что это какая-то вещь типа генератора, и скорость обучения невидимо снижается: как я могу запустить оптимизатор adam, не разлагая скорость обучения? Мне кажется, что RMSProp в основном то же самое, единственное, что мне нужно сделать, чтобы сделать его равным (скорость обучения не учитывается) заключается в изменении гиперпараметров momentum
и decay
для соответствия beta1
и beta2
соответственно. Это правильно?
Ответы
Ответ 1
Я нахожу документацию совершенно ясной, я вложу здесь алгоритм в псевдокод:
Параметры:
-
learning_rate
: между 1е-4 и 1е-2 стандартно
-
beta1
: 0.9 по умолчанию
-
beta2
: 0.999 по умолчанию
-
epsilon
: 1e-08 по умолчанию
Значение по умолчанию 1e-8 для epsilon не может быть хорошим дефолтом в целом. Например, при обучении начальной сети в ImageNet текущий хороший выбор - 1,0 или 0,1.
Инициализация:
m_0 <- 0 (Initialize initial 1st moment vector)
v_0 <- 0 (Initialize initial 2nd moment vector)
t <- 0 (Initialize timestep)
m_t
и v_t
будут отслеживать скользящее среднее градиента и его квадрата для каждого параметра сети. (Итак, если у вас есть 1M-параметры, Adam сохранит в памяти 2M больше параметров)
На каждой итерации t
и для каждого параметра модели:
t <- t + 1
lr_t <- learning_rate * sqrt(1 - beta2^t) / (1 - beta1^t)
m_t <- beta1 * m_{t-1} + (1 - beta1) * gradient
v_t <- beta2 * v_{t-1} + (1 - beta2) * gradient ** 2
variable <- variable - lr_t * m_t / (sqrt(v_t) + epsilon)
Здесь lr_t
немного отличается от learning_rate
, потому что для ранних итераций скользящие средние еще не сходились, поэтому нам нужно нормализовать, умножив на sqrt(1 - beta2^t) / (1 - beta1^t)
. Когда t
высокий (t > 1./(1.-beta2)
), lr_t
почти равен learning_rate
Чтобы ответить на ваш вопрос, вам просто нужно пройти фиксированную скорость обучения, сохранить beta1
и beta2
значения по умолчанию, возможно изменить epsilon
, и Адам сделает магию:)
Ссылка с RMSProp
Адам с beta1=1
эквивалентен RMSProp с momentum=0
. Аргумент beta2
Адама и аргумент decay
RMSProp одинаковы.
Однако RMSProp не сохраняет скользящее среднее градиента. Но он может поддерживать импульс, например MomentumOptimizer.
Подробное описание rmsprop.
- поддерживать перемещаемое (дисконтированное) среднее значение квадрата градиентов
- разделите градиент на корень этого среднего
- (может поддерживать импульс)
Вот псевдокод:
v_t <- decay * v_{t-1} + (1-decay) * gradient ** 2
mom = momentum * mom{t-1} + learning_rate * gradient / sqrt(v_t + epsilon)
variable <- variable - mom
Ответ 2
RMS_PROP и ADAM имеют адаптивную скорость обучения.
Основной RMS_PROP
cache = decay_rate * cache + (1 - decay_rate) * dx**2
x += - learning_rate * dx / (np.sqrt(cache) + eps)
Вы можете видеть, что изначально это имеет два параметра: decay_rate и eps
Тогда мы можем добавить импульс, чтобы сделать наш градиент более устойчивым. Тогда мы можем написать
cache = decay_rate * cache + (1 - decay_rate) * dx**2
**m = beta1*m + (1-beta1)*dx** [beta1 =momentum parameter in the doc ]
x += - learning_rate * dx / (np.sqrt(cache) + eps)
Теперь вы можете увидеть здесь, если мы будем держать beta1 = o Затем он rms_prop без импульса.
Затем Основы ADAM
В cs-231 Andrej Karpathy изначально описал адама как это
Адам - недавно появившееся обновление, которое немного похоже на RMSProp с импульс
Итак, да! Тогда чем это отличается от rms_prop с импульсом?
m = beta1*m + (1-beta1)*dx
v = beta2*v + (1-beta2)*(dx**2)
**x += - learning_rate * m / (np.sqrt(v) + eps)**
Он снова упомянул в уравнении обновления m, v более гладкие.
Таким образом, отличие от rms_prop - это обновление менее шумно.
Что делает этот шум?
Хорошо в процедуре инициализации мы инициализируем m и v как ноль.
т = у = 0
Чтобы уменьшить этот эффект инициализации, всегда нужно провести разминку. Итак, уравнение похоже на
m = beta1*m + (1-beta1)*dx beta1 -o.9 beta2-0.999
**mt = m / (1-beta1**t)**
v = beta2*v + (1-beta2)*(dx**2)
**vt = v / (1-beta2**t)**
x += - learning_rate * mt / (np.sqrt(vt) + eps)
Теперь мы запускаем это для нескольких итераций. Четко обратите внимание на жирные линии, вы можете видеть, когда t увеличивается (номер итерации), следующая вещь с mt,
mt = m