Подтвердить что ты не робот

Как установить адаптивную скорость обучения для GradientDescentOptimizer?

Я использую TensorFlow для обучения нейронной сети. Вот как я инициализирую GradientDescentOptimizer:

init = tf.initialize_all_variables()
sess = tf.Session()
sess.run(init)

mse        = tf.reduce_mean(tf.square(out - out_))
train_step = tf.train.GradientDescentOptimizer(0.3).minimize(mse)

Дело в том, что я не знаю, как установить правило обновления для скорости обучения или значения распада для этого.

Как я могу использовать скорость адаптивного обучения здесь?

4b9b3361

Ответ 1

Прежде всего, tf.train.GradientDescentOptimizer предназначен для использования постоянной скорости обучения для всех переменных на всех этапах. TensorFlow также предоставляет готовые адаптивные оптимизаторы, включая tf.train.AdagradOptimizer и tf.train.AdamOptimizer, и они могут использоваться как замены для замены.

Однако, если вы хотите контролировать скорость обучения с помощью градиентного спуска в противном случае, вы можете воспользоваться тем фактом, что аргумент learning_rate для конструктора tf.train.GradientDescentOptimizer может быть объектом Tensor. Это позволяет вам вычислять другое значение для скорости обучения на каждом этапе, например:

learning_rate = tf.placeholder(tf.float32, shape=[])
# ...
train_step = tf.train.GradientDescentOptimizer(
    learning_rate=learning_rate).minimize(mse)

sess = tf.Session()

# Feed different values for learning rate to each training step.
sess.run(train_step, feed_dict={learning_rate: 0.1})
sess.run(train_step, feed_dict={learning_rate: 0.1})
sess.run(train_step, feed_dict={learning_rate: 0.01})
sess.run(train_step, feed_dict={learning_rate: 0.01})

В качестве альтернативы вы можете создать скаляр tf.Variable, который содержит скорость обучения, и назначать его каждый раз, когда вы хотите изменить скорость обучения.

Ответ 2

Tensorflow обеспечивает автоматическое применение экспоненциального распада к тензору скорости обучения: tf.train.exponential_decay. Пример его использования см. В этой строке в примере сверточной модели MNIST. Затем используйте предложение @mrry выше, чтобы предоставить эту переменную в качестве параметра learn_rate вашему оптимизатору выбора.

Ключевой отрывок для просмотра:

# Optimizer: set up a variable that incremented once per batch and
# controls the learning rate decay.
batch = tf.Variable(0)

learning_rate = tf.train.exponential_decay(
  0.01,                # Base learning rate.
  batch * BATCH_SIZE,  # Current index into the dataset.
  train_size,          # Decay step.
  0.95,                # Decay rate.
  staircase=True)
# Use simple momentum for the optimization.
optimizer = tf.train.MomentumOptimizer(learning_rate,
                                     0.9).minimize(loss,
                                                   global_step=batch)

Обратите внимание на параметр global_step=batch, чтобы свести к минимуму. Это говорит оптимизатору, чтобы помочь вам постепенно увеличивать параметр "batch" каждый раз, когда он тренируется.

Ответ 3

Алгоритм спуска градиента использует постоянную скорость обучения, которую вы можете предоставить в во время инициализации. Вы можете передавать различные учебные курсы таким образом, который показал Мрри.

Вместо этого вы также можете использовать более продвинутые оптимизаторы, которые имеют более высокую скорость конвергенции и адаптируются к ситуации.

Вот краткое объяснение, основанное на моем понимании:

  • импульс помогает SGD перемещаться по соответствующим направлениям и смягчает колебания в нерелевантности. Он просто добавляет часть направления предыдущего шага к текущему шагу. Это обеспечивает усиление скорости в правильном направлении и смягчает колебания в неправильных направлениях. Эта доля обычно находится в диапазоне (0, 1). Также имеет смысл использовать адаптивный импульс. В начале обучения большой импульс будет только мешать вашему прогрессу, поэтому имеет смысл использовать что-то вроде 0,01, и как только все градиенты исчезнут, вы можете использовать больший импульс. Есть одна проблема с импульсом: когда мы очень близки к цели, наш импульс в большинстве случаев очень высок, и он не знает, что он должен замедляться. Это может привести к пропуску или колебанию вокруг минимумов.
  • Нестеров ускоренный градиент преодолевает эту проблему, начиная рано замедляться. В импульсе мы сначала вычисляем градиент, а затем делаем скачок в этом направлении, усиленный каким-либо импульсом, который мы имели ранее. NAG делает то же самое, но в другом порядке: сначала мы делаем большой прыжок на основе нашей хранимой информации, а затем вычисляем градиент и делаем небольшую коррекцию. Это, казалось бы, неуместное изменение дает значительные практические ускорения.
  • AdaGrad или адаптивный градиент позволяет адаптировать курс обучения на основе параметров. Он выполняет большие обновления для нечастых параметров и небольших обновлений для частых. Из-за этого он хорошо подходит для разреженных данных (NLP или распознавание изображений). Другим преимуществом является то, что он в основном лимитирует необходимость настройки скорости обучения. Каждый параметр имеет собственную скорость обучения, и из-за особенностей алгоритма скорость обучения монотонно уменьшается. Это вызывает самую большую проблему: в некоторый момент времени скорость обучения настолько мала, что система перестает учиться
  • AdaDelta​​strong > решает проблему монотонно уменьшающейся скорости обучения в AdaGrad. В AdaGrad коэффициент обучения был рассчитан приблизительно как один, деленный на сумму квадратных корней. На каждом этапе вы добавляете еще один квадратный корень в сумму, что приводит к тому, что знаменатель постоянно уменьшается. В AdaDelta вместо суммирования всех прошлых квадратных корней он использует скользящее окно, которое позволяет уменьшить сумму. RMSprop очень похож на AdaDelta​​li >
  • Adam или адаптивный импульс - это алгоритм, подобный AdaDelta. Но помимо хранения скоростей обучения для каждого из параметров он также сохраняет изменения импульса для каждого из них отдельно.

    A несколько визуализаций: введите описание изображения здесь введите описание изображения здесь

Ответ 4

Из официальных документов tendorflow

global_step = tf.Variable(0, trainable=False)
starter_learning_rate = 0.1
learning_rate = tf.train.exponential_decay(starter_learning_rate, global_step,
                                       100000, 0.96, staircase=True)

# Passing global_step to minimize() will increment it at each step.
learning_step = (
tf.train.GradientDescentOptimizer(learning_rate)
.minimize(...my loss..., global_step=global_step))

Ответ 5

Если вы хотите установить конкретные скорости обучения для интервалов эпох, например, 0 < a < b < c <... Затем вы можете определить свою скорость обучения как условный тензор, зависящий от глобального шага, и передать его как обычно оптимизатору.

tf.cond можно достичь с помощью нескольких вложенных операторов tf.cond, но рекурсивно построить тензор проще:

def make_learning_rate_tensor(reduction_steps, learning_rates, global_step):
    assert len(reduction_steps) + 1 == len(learning_rates)
    if len(reduction_steps) == 1:
        return tf.cond(
            global_step < reduction_steps[0],
            lambda: learning_rates[0],
            lambda: learning_rates[1]
        )
    else:
        return tf.cond(
            global_step < reduction_steps[0],
            lambda: learning_rates[0],
            lambda: make_learning_rate_tensor(
                reduction_steps[1:],
                learning_rates[1:],
                global_step,)
            )

Затем, чтобы использовать его, вам нужно знать, сколько этапов обучения имеется в одной эпохе, чтобы мы могли использовать глобальный шаг для переключения в нужное время и, наконец, определить нужные вам эпохи и скорости обучения. Поэтому, если я хочу, чтобы скорости обучения [0.1, 0.01, 0.001, 0.0001] в интервалы эпох [0, 19], [20, 59], [60, 99], [100, \infty] соответственно, я бы сделал:

global_step = tf.train.get_or_create_global_step()
learning_rates = [0.1, 0.01, 0.001, 0.0001]
steps_per_epoch = 225
epochs_to_switch_at = [20, 60, 100]
epochs_to_switch_at = [x*steps_per_epoch for x in epochs_to_switch_at ]
learning_rate = make_learning_rate_tensor(epochs_to_switch_at , learning_rates, global_step)