Градиенты TensorFlow: получение ненужных градиентов 0.0 с помощью tf.gradients

Предположим, у меня есть следующая переменная

embeddings = tf.Variable (tf.random_uniform (dtype = tf.float32, shape = [self.vocab_size, self.embedding_dim], minval = -0.001, maxval = 0.001))

sent_1 = construct_sentence (word_ids_1)

отправлено_2 = конструкция_предложение (идентификаторы_слова_2)

Где construct_sentence - это метод получения представления предложения на основе заполнителей word_ids_1 и word_ids_2

Предположим, у меня есть потеря:

потеря = construct_loss (отправлено_1, отправлено_2, метка)

Теперь, когда я пытаюсь получить градиенты, используя:

gradient_wrt_w = tf.gradients (потеря, вложения)

Вместо того, чтобы получать только градиенты по отношению к конкретным переменным, участвующим в construct_sentence и construct_loss, я получаю градиенты каждого вложения в переменную embeddings (градиенты равны 0 для тех вложений, которые не участвуют в представлениях потерь и предложений).

Как получить градиенты по интересующим меня переменным?

Более того, я получаю повторения некоторых переменных (с одним и тем же значением) из-за задействованных частных производных. Поскольку вложения - это 2D-переменная, я не могу выполнить простой поиск, подобный этому:

tf.gradients (потеря, tf.nn.embedding_lookup (вложения, word_ids))

Это приводит к огромному снижению производительности, поскольку я работаю с большим количеством встраиваний слов и хочу использовать производную только по некоторым вложениям слов за раз.

Более того, я получаю много повторяющихся градиентов (из-за частных производных), и я пытался использовать tf.AggregationMethod, но это не сработало.


person Want    schedule 05.02.2018    source источник
comment
Может быть, вы можете попробовать заставить вас встраивать переменные vocab_size количество переменных, за которыми следует concat?   -  person suharshs    schedule 05.02.2018
comment
Вы пытались определить embeddings с помощью Trainable=False в конструкторе? См .: tensorflow.org/api_docs/python/tf/Variable#initializer   -  person mikkola    schedule 05.02.2018
comment
@mikkola Это не работает.   -  person Want    schedule 07.02.2018
comment
@suharshs Как это поможет? Это приведет к тому же.   -  person Want    schedule 07.02.2018


Ответы (1)


Вы не можете делать tf.gradients(loss, tf.nn.embedding_lookup(embeddings, word_ids)), но можете делать прямо tf.gradients(loss, embeddings), и это даст вам tf.IndexedSlices объект, содержащий только градиенты идентификаторов затронутых слов.

Что касается агрегирования градиентов, соответствующих повторяющимся идентификаторам слов, это автоматически выполняется при вызове optimizer.apply_gradients, но вы можете воспроизвести это с помощью tf.unsorted_segment_sum и tf.unique следующим образом:

embedding_table = tf.random_uniform((10, 5))
word_ids = tf.placeholder(shape=(None), dtype=tf.int32)
temp_emb = tf.nn.embedding_lookup(embedding_table, word_ids)
loss = tf.reduce_sum(temp_emb, axis=0)

g = tf.gradients(loss, embedding_table)[0].values
repeating_indices = tf.gradients(loss, embedding_table)[0].indices # This is the same as word_ids.

unique_indices, idx_in_repeating_indices = tf.unique(repeating_indices)

agg_gradients = tf.unsorted_segment_sum(g,
                                        idx_in_repeating_indices,
                                        tf.shape(unique_indices)[0])

sess = tf.Session()
unique_indices_v, agg_gradients_v, _ = \
    sess.run([unique_indices, agg_gradients, loss],
         feed_dict={word_ids: np.array([6, 1, 5, 1, 1, 5])})


print(unique_indices_v)
print(agg_gradients_v)

давая для приведенного выше примера:

[6 1 5]

[[1. 1. 1. 1. 1.]
 [3. 3. 3. 3. 3.]
 [2. 2. 2. 2. 2.]]
person Octavian Ganea    schedule 07.05.2018