【问题标题】:How to modify the return tensor from tf.nn.embedding_lookup()?如何从 tf.nn.embedding_lookup() 修改返回张量?
【发布时间】:2018-05-09 17:30:39
【问题描述】:

我想用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)

【问题讨论】:

    标签: python tensorflow machine-learning embedding tensor


    【解决方案1】:

    tf.nn.embedding_lookup 只是返回较大矩阵的切片,因此最简单的解决方案是更新 that 矩阵本身的值,在您的情况下为self.W

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

    因为它是一个变量,所以它符合tf.scatter_nd_update。请注意,您不能只更新任何张量,只能更新变量

    另一种选择是仅为所选切片创建一个新变量,将self.embedded_chars 分配给它,然后执行更新。


    警告:在这两种情况下,您都在阻止梯度来训练嵌入矩阵,因此请仔细检查覆盖学习值是否真的是您想要的。

    【讨论】:

    • 非常感谢您的解释。你能说更多关于警告的信息吗?我想在输入层修改一些张量,比如做一些加法或减法。
    • 可以修改原始输入数据(称为预处理)。您在问题中描述的是在培训过程中覆盖价值。或者我可能不明白你的目标。
    • 我想我正在做预处理,因为它是在卷积发生之前完成的。我想连接每个词嵌入或进行减法以获得嵌入偏移量,然后馈送到卷积层。所以我认为这不会破坏训练。不是吗?
    • 不,这很重要。嵌入是可学习的(除非它是预先训练和固定的),所以它已经是网络的一部分。 您输入数据之前对数据进行预处理,在本例中为字符索引。
    • 我使用在谷歌语料库(GoogleNews-vectors-negative300)上训练的预训练 word2vec 嵌入。它加载在 self.W 中。然后通过使用 embedding_lookup 来获取句子中每个单词的向量并作为输入。我想要做的是在输入层将这些词向量连接或减去,然后馈送到卷积层。我认为只有权重矩阵是可学习的,并且输入层的嵌入是固定的。我说的对吗?
    【解决方案2】:

    这个问题源于没有清楚地理解tensorflow上下文中的张量和变量。后来随着对张量的更多了解,我想到的解决方案是:

       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 这样需要变量作为输入的函数。

    【讨论】:

      猜你喜欢
      • 2020-07-16
      • 2015-08-18
      • 2016-09-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-03
      • 2021-02-23
      • 1970-01-01
      • 2014-03-10
      相关资源
      最近更新 更多