Учитывая пример кода .
Я хотел бы знать, как применить градиентное отсечение в этой сети в RNN, где есть возможность взрывных градиентов.
tf.clip_by_value(t, clip_value_min, clip_value_max, name=None)
Это пример, который можно использовать, но где мне его представить? В деф РНН
lstm_cell = rnn_cell.BasicLSTMCell(n_hidden, forget_bias=1.0)
# Split data because rnn cell needs a list of inputs for the RNN inner loop
_X = tf.split(0, n_steps, _X) # n_steps
tf.clip_by_value(_X, -1, 1, name=None)
Но это не имеет смысла, поскольку тензор _X является входом, а не градиентом, который нужно обрезать?
Нужно ли мне определять для этого свой собственный оптимизатор или есть более простой вариант?
источник
optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(cost)
затем выполняется итерация оптимизатора,optimizer.run()
но использованиеoptimizer.run()
в этом случае не работает?optimizer.apply_gradients(capped_gvs)
x = optimizer.apply_gradients(capped_gvs)
x.run(...)
UserWarning: Converting sparse IndexedSlices to a dense Tensor with 148331760 elements. This may consume a large amount of memory.
Итак, мои разреженные градиенты каким-то образом превращаются в плотные. Есть идеи, как решить эту проблему?tf.clip_by_global_norm
, как предлагает @danijarНесмотря на то, что кажется популярным, вы, вероятно, захотите обрезать весь градиент по его глобальной норме:
Отсечение каждой градиентной матрицы индивидуально изменяет их относительный масштаб, но также возможно:
В TensorFlow 2 лента вычисляет градиенты, оптимизаторы поступают из Keras, и нам не нужно хранить операцию обновления, потому что она запускается автоматически, не передавая ее сеансу:
источник
clip_by_global_norm()
! Это также описаноthe correct way to perform gradient clipping
в документации по тензорномуtf.global_norm(gradients)
чтобы увидеть ее обычный диапазон, а затем вырезать немного выше этого, чтобы выбросы не испортили обучение.opt.minimize()
после этого или вы бы назвали что-то другое,opt.run()
как это предлагается в некоторых комментариях к другим ответам?optimizer.minimize(loss)
это просто сокращение для вычисления и применения градиентов. Вы можете запустить пример в моем ответе с помощьюsess.run(optimize)
.tf.estimator.EstimatorSpec(mode, loss=loss, train_op=train_op)
функцию эксперимента, то выoptimize
бы заменили моюtrain_op
правильную? Прямо сейчас мой,train_op = optimizer.minimize(loss, global_step=global_step))
так что я пытаюсь убедиться, что я соответствующим образомНа самом деле это правильно объяснено в документации. :
И в приведенном ими примере они используют эти 3 шага:
Вот
MyCapper
любая функция, которая ограничивает ваш градиент. Список полезных функций (кромеtf.clip_by_value()
) находится здесь .источник
opt.minimize()
после этого или вы бы назвали что-то другое,opt.run()
как это предлагается в некоторых комментариях к другим ответам?opt.apply_gradients(...)
переменную,train_step
например (точно так же, как и дляopt.minimize()
. И в своем основном цикле вы называете это, как обычно, для тренировки)sess.run([train_step, ...], feed_dict)
tf.clip_by_global_norm(list_of_tensors)
).Для тех, кто хотел бы понять идею градиентного отсечения (по норме):
Каждый раз, когда норма градиента превышает определенный порог, мы обрезаем норму градиента, чтобы она оставалась в пределах порога. Иногда этот порог устанавливается равным
5
.Пусть градиент равен g, а max_norm_threshold равен j .
Теперь, если || г || > j , делаем:
g = ( j * g ) / || г ||
Это реализация, сделанная в
tf.clip_by_norm
источник
IMO лучшее решение - обернуть ваш оптимизатор декоратором оценки TF
tf.contrib.estimator.clip_gradients_by_norm
:Таким образом, вам нужно определить это только один раз, а не запускать его после каждого вычисления градиентов.
Документация: https://www.tensorflow.org/api_docs/python/tf/contrib/estimator/clip_gradients_by_norm
источник
Градиентное отсечение в основном помогает в случае взрывающихся или исчезающих градиентов. Скажите, что ваши потери слишком велики, что приведет к экспоненциальным градиентам, которые будут течь по сети, что может привести к значениям Nan. Чтобы преодолеть это, мы обрезаем градиенты в пределах определенного диапазона (от -1 до 1 или любого диапазона в соответствии с условием).
clipped_value=tf.clip_by_value(grad, -range, +range), var) for grad, var in grads_and_vars
где grads _and_vars - это пары градиентов (которые вы вычисляете с помощью tf.compute_gradients) и их переменные, к которым они будут применяться.
После отсечения мы просто применяем его значение с помощью оптимизатора.
optimizer.apply_gradients(clipped_value)
источник