Как использовать stop_gradient в Tensorflow
Мне интересно, как использовать stop_gradient
в tensorflow, и документация мне не понятна.
В настоящее время я использую stop_gradient
для создания градиента функции потерь w.r.t. слово вложения в модели CBOW word2vec. Я хочу просто получить значение, а не делать backpropagation (поскольку я создаю состязательные примеры).
В настоящее время я использую код:
lossGrad = gradients.gradients(loss, embed)[0]
real_grad = lossGrad.eval(feed_dict)
Но когда я запускаю это, он делает backpropogation в любом случае! Что я делаю неправильно, и так же важно, как я могу это исправить?
ПОДТВЕРЖДЕНИЕ: Чтобы уточнить "backpropagation", я имею в виду "вычисление значений и обновление параметров модели".
UPDATE
Если я запустил две строки выше после первого этапа обучения, я получаю другую потерю после 100 шагов обучения, чем когда я не запускаю эти две строки. Я мог бы принципиально не понимать что-то о Tensorflow.
Я попытался установить с помощью set_random_seed
как в начале объявления графика, так и перед каждым шагом обучения. Полная потеря согласована между несколькими прогонами, но не между включением/исключением этих двух строк. Итак, если это не RNG, вызывающий диспропорцию, и это не непредвиденное обновление параметров модели между этапами обучения, знаете ли вы, что могло бы вызвать это поведение?
РЕШЕНИЕ
Welp, это немного поздно, но вот, как я это решил. Я только хотел оптимизировать некоторые, но не все, переменные. Я думал, что способ предотвратить оптимизацию некоторых переменных будет заключаться в использовании stop_grad
- но я никогда не нашел способ сделать эту работу. Возможно, есть способ, но для меня работала настройка optimizer
только для оптимизации списка переменных. Поэтому вместо:
opt = tf.train.GradientDescentOptimizer(learning_rate=eta)
train_op = opt.minimize(loss)
Я использовал:
opt = tf.train.GradientDescentOptimizer(learning_rate=eta)
train_op = opt.minimize(loss, var_list=[variables to optimize over])
Это предотвратило opt
от обновления переменных не в var_list
. Надеюсь, это сработает и для вас!
Ответы
Ответ 1
tf.gradients(loss, embed)
вычисляет частную производную тензора loss
относительно тензора embed
. TensorFlow вычисляет эту частную производную путем backpropagation, поэтому ожидается, что поведение, которое оценивает результат tf.gradients(...)
, выполняет обратное распространение. Однако, оценивая, что тензор не выполняет никаких переменных обновлений, потому что выражение не включает в себя операции назначения.
tf.stop_gradient()
- это операция, которая действует как функция идентификации в прямом направлении, но останавливает накопленный градиент от прохождения через этот оператор в обратном направлении. Это не предотвращает обратное распространение вообще, но вместо этого предотвращает внесение отдельного тензора в градиенты, которые вычисляются для выражения. документация для операции содержит более подробную информацию об операции и когда ее использовать.
Ответ 2
tf.stop_gradient предоставляет возможность не вычислять градиент по отношению к некоторым переменным во время обратного распространения.
Например, в приведенном ниже коде мы имеем три переменные: w1, w2, w3 и вход x. Потеря квадрата ((x1.dot(w1) - x.dot(w2 * w3))). Мы хотим минимизировать эту потерю по w1, но хотим сохранить w2 и w3 фиксированными. Для этого мы можем просто положить tf.stop_gradient (tf.matmul(x, w2 * w3)).
На рисунке ниже я описал, как w1, w2 и w3 от их начальных значений как функция тренировочных итераций. Видно, что w2 и w3 остаются фиксированными, а w1 изменяется до тех пор, пока не станет равным w2 * w3.
Изображение, показывающее, что w1 только узнает, но не w2 и w3
import tensorflow as tf
import numpy as np
w1 = tf.get_variable("w1", shape=[5, 1], initializer=tf.truncated_normal_initializer())
w2 = tf.get_variable("w2", shape=[5, 1], initializer=tf.truncated_normal_initializer())
w3 = tf.get_variable("w3", shape=[5, 1], initializer=tf.truncated_normal_initializer())
x = tf.placeholder(tf.float32, shape=[None, 5], name="x")
a1 = tf.matmul(x, w1)
a2 = tf.matmul(x, w2*w3)
a2 = tf.stop_gradient(a2)
loss = tf.reduce_mean(tf.square(a1 - a2))
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.1)
gradients = optimizer.compute_gradients(loss)
train_op = optimizer.apply_gradients(gradients)