Как ограничить абсолютное значение каждого измерения разреженного градиента от слишком большого? - PullRequest
0 голосов
/ 02 сентября 2018

Рассмотрим код ниже:

import tensorflow as tf

inputs=tf.placeholder(tf.int32, [None])
labels=tf.placeholder(tf.int32, [None])

with tf.variable_scope('embedding'):
    embedding=tf.get_variable('embedding', shape=[2000000, 300], dtype=tf.float32)

layer1=tf.nn.embedding_lookup(embedding, inputs)
logits=tf.layers.dense(layer1, 2000000)

loss=tf.nn.sparse_softmax_cross_entropy_with_logits(labels=labels, logits=logits)
cost=tf.reduce_sum(loss)

optimizer=tf.train.GradientDescentOptimizer(0.01)
grads, vars=zip(*optimizer.compute_gradients(cost))
for g in grads:
    print(0, g)

grads1=[tf.clip_by_value(g, -100, 100) for g in grads]
for g in grads1:
    print(1, g)

grads2, _=tf.clip_by_global_norm(grads, 10)
for g in grads2:
    print(2, g)

Вывод:

0 IndexedSlices(indices=Tensor("gradients/embedding_lookup_grad/Reshape_1:0", shape=(?,), dtype=int32), values=Tensor("gradients/embedding_lookup_grad/Reshape:0", shape=(?, 300), dtype=float32), dense_shape=Tensor("gradients/embedding_lookup_grad/ToInt32:0", shape=(2,), dtype=int32))
0 Tensor("gradients/dense/MatMul_grad/tuple/control_dependency_1:0", shape=(300, 2000000), dtype=float32)
0 Tensor("gradients/dense/BiasAdd_grad/tuple/control_dependency_1:0", shape=(2000000,), dtype=float32)
C:\Python\Python36\lib\site-packages\tensorflow\python\ops\gradients_impl.py:97: UserWarning: Converting sparse IndexedSlices to a dense Tensor with 600000000 elements. This may consume a large amount of memory.
  num_elements)
1 Tensor("clip_by_value:0", shape=(?, 300), dtype=float32)
1 Tensor("clip_by_value_1:0", shape=(300, 2000000), dtype=float32)
1 Tensor("clip_by_value_2:0", shape=(2000000,), dtype=float32)
2 IndexedSlices(indices=Tensor("gradients/embedding_lookup_grad/Reshape_1:0", shape=(?,), dtype=int32), values=Tensor("clip_by_global_norm/clip_by_global_norm/_0:0", shape=(?, 300), dtype=float32), dense_shape=Tensor("gradients/embedding_lookup_grad/ToInt32:0", shape=(2,), dtype=int32))
2 Tensor("clip_by_global_norm/clip_by_global_norm/_1:0", shape=(300, 2000000), dtype=float32)
2 Tensor("clip_by_global_norm/clip_by_global_norm/_2:0", shape=(2000000,), dtype=float32)

Я знаю, что есть два способа ограничить слишком большие градиенты. tf.clip_by_value для ограничения каждого размера и tf.clip_by_global_norm для ограничения в соответствии с нормами глобальных градиентов.

Тем не менее, tf.clip_by_value преобразует разреженный градиент в плотный, что значительно увеличивает использование памяти и снижает эффективность вычислений, как указывает предупреждение, а tf.clip_by_global_norm - нет. Хотя я могу понять, почему это разработано, как я могу ограничить абсолютное значение каждого измерения разреженного градиента слишком большим без снижения эффективности?

Пожалуйста, не говорите мне, просто используйте tf.clip_by_global_norm, я знаю, что это нормально для большинства случаев, но это не то, что я хочу.

1 Ответ

0 голосов
/ 18 октября 2018

Теперь я использую это, оно работает хорошо.

grads=[tf.IndexedSlices(tf.clip_by_value(g.values, -max_grad_value, max_grad_value), g.indices, g.dense_shape) if isinstance(g, tf.IndexedSlices) else tf.clip_by_value(g, -max_grad_value, max_grad_value) for g in grads]
...