Тонко-плотное градиентное объяснение?
Недавно я реализовал модель, и когда я ее запустил, я получил это предупреждение:
UserWarning: Converting sparse IndexedSlices to a dense Tensor of unknown shape.
This may consume a large amount of memory.
"Converting sparse IndexedSlices to a dense Tensor of unknown shape. "
С некоторыми подобными настройками параметров (встраивание мерностей) внезапно модель смехотворно медленна.
- Что означает это предупреждение? Похоже, что что-то, что я сделал, привело к тому, что все градиенты были плотными, и поэтому backprop выполняет плотные вычисления матрицы.
- Если это проблема с моделью, которая вызывает это, как я могу ее идентифицировать и исправить?
Ответы
Ответ 1
Это предупреждение печатается, когда разреженный tf.IndexedSlices
объект неявно преобразуется в плотный tf.Tensor
. Обычно это происходит, когда один op (обычно tf.gather()
) backpropagates разреженный градиент, но тот, который его получает, не имеет специализированной функции градиента, которая может обрабатывать разреженные градиенты. В результате TensorFlow автоматически уплотняет tf.IndexedSlices
, что может оказать разрушительное воздействие на производительность, если тензор большой.
Чтобы устранить эту проблему, следует попытаться убедиться, что вход params
в tf.gather()
(или входы params
в tf.nn.embedding_lookup()
) a tf.Variable
. Переменные могут получать разреженные обновления напрямую, поэтому преобразование не требуется. Хотя tf.gather()
(и tf.nn.embedding_lookup()
) принимают произвольные тензоры в качестве входных данных, это может привести к более сложному графику backpropagation, что приведет к неявному преобразованию.
Ответ 2
Плотный тензор можно рассматривать как стандартный массив python. Редкую можно рассматривать как совокупность индексов и значений, например.
# dense
array = ['a', None, None, 'c']
# sparse
array = [(0, 'a'), (3, 'c')]
Итак, если вы видите, что у вас много пустых записей, разреженный массив будет намного эффективнее плотного. Но если все записи заполнены, плотность намного эффективнее. В вашем случае где-нибудь в графе тензорного потока разреженный массив преобразуется в плотный один из неопределенных размеров. Предупреждение просто говорит, что возможно, что вы можете тратить много памяти, как это. Но это может быть не проблема, если разреженный массив не слишком большой/уже довольно плотный.
Если вы хотите диагностировать его, я бы посоветовал называть ваши различные тензорные объекты, тогда он будет печатать точно, какие из них используются в этом преобразовании, и вы можете решить, что вы можете настроить, чтобы удалить его.
Ответ 3
Полностью согласен с ответом mrry
.
На самом деле я отправлю еще одно решение этой проблемы.
Вы можете использовать tf.dynamic_partition()
вместо tf.gather()
, чтобы устранить предупреждение.
Пример кода ниже:
# Create the cells for the RNN network
lstm = tf.nn.rnn_cell.BasicLSTMCell(128)
# Get the output and state from dynamic rnn
output, state = tf.nn.dynamic_rnn(lstm, sequence, dtype=tf.float32, sequence_length = seqlen)
# Convert output to a tessor and reshape it
outputs = tf.reshape(tf.pack(output), [-1, lstm.output_size])
# Set partions to 2
num_partitions = 2
# The partitions argument is a tensor which is already fed to a placeholder.
# It is a 1-D tensor with the length of batch_size * max_sequence_length.
# In this partitions tensor, you need to set the last output idx for each seq to 1 and
# others remain 0, so that the result could be separated to two parts,
# one is the last outputs and the other one is the non-last outputs.
res_out = tf.dynamic_partition(outputs, partitions, num_partitions)
# prediction
preds = tf.matmul(res_out[1], weights) + bias
Надеюсь, это поможет вам.