Как изменить тензор возврата из tf.nn.embedding_lookup ()? - PullRequest
0 голосов
/ 09 мая 2018

Я хочу использовать scatter_nd_update для изменения содержимого тензора, возвращаемого с tf.nn.embedding_lookup(). Однако возвращенный тензор не является изменяемым, а scatter_nd_update() требует изменяемого тензора в качестве входных данных. Я потратил много времени, пытаясь найти решение, в том числе с помощью gen_state_ops._temporary_variable и tf.sparse_to_dense, к сожалению, все не удалось.

Интересно, есть ли прекрасное решение в этом направлении?

with tf.device('/cpu:0'), tf.name_scope("embedding"):
            self.W = tf.Variable(
                tf.random_uniform([vocab_size, embedding_size], -1.0, 1.0),
                name="W")
            self.embedded_chars = tf.nn.embedding_lookup(self.W, self.input_x)
            updates = tf.constant(0,shape=[embedding_size])
            for i in range(1,sequence_length - 2):
                indices = [None,i]
                tf.scatter_nd_update(self.embedded_chars,indices,updates)
            self.embedded_chars_expanded = tf.expand_dims(self.embedded_chars, -1)

Ответы [ 2 ]

0 голосов
/ 11 мая 2018

В основе этой проблемы лежит нечеткое понимание тензора и переменной в контексте тензорного потока. Позже, с большим знанием тензора, мне пришло в голову решение:

   with tf.device('/cpu:0'), tf.name_scope("embedding"):
        self.W = tf.Variable(
            tf.random_uniform([vocab_size, embedding_size], -1.0, 1.0),
            name="W")
        self.embedded_chars = tf.nn.embedding_lookup(self.W, self.input_x)
        for i in range(0,sequence_length - 1,2):
            self.tslice = tf.slice(self.embedded_chars,[0,i,0],[0,1,128])
            self.tslice2 = tf.slice(self.embedded_chars,[0,i+1,0],[0,1,128])
            self.tslice3 = tf.slice(self.embedded_chars,[0,i+2,0],[0,1,128])
            self.toffset1 = tf.subtract(self.tslice,self.tslice2)
            self.toffset2 = tf.subtract(self.tslice2,self.tslice3)
            self.tconcat = tf.concat([self.toffset1,self.toffset2],1)
        self.embedded_chars_expanded = tf.expand_dims(self.embedded_chars, -1)

используемая функция, tf.slice, tf.subtract, tf.concat - все принимают тензор в качестве входных данных. Просто избегайте использования такой функции, как tf.scatter_nd_update, для которой в качестве входных данных требуется переменная.

0 голосов
/ 09 мая 2018

tf.nn.embedding_lookup просто возвращает фрагмент большей матрицы, поэтому самое простое решение - обновить значение этой самой матрицы, в вашем случае это self.W:

self.embedded_chars = tf.nn.embedding_lookup(self.W, self.input_x)

Поскольку это переменная, она соответствует tf.scatter_nd_update. Обратите внимание, что вы не можете обновить только любой тензор, только переменные .

Другой вариант - создать новую переменную только для выбранного среза, присвоить ей self.embedded_chars и впоследствии выполнить обновление.


Предостережение: в обоих случаях вы блокируете градиенты для обучения матрицы встраивания, поэтому дважды проверьте, что перезапись полученного значения действительно то, что вам нужно.

...