【问题标题】:How to assign values to a subset of a tensor in tensorflow?如何为张量流中的张量子集赋值?
【发布时间】:2016-10-27 23:23:24
【问题描述】:

这个问题的两个部分:

(1) 在 tensorflow 中更新张量子集的最佳方法是什么?我看过几个相关的问题:

Adjust Single Value within Tensor -- TensorFlowHow to update a subset of 2D tensor in Tensorflow?

而且我知道可以使用 Variable.assign()(和/或 scatter_update 等)分配变量对象,但对我来说 tensorflow 没有更直观的方式来更新部件似乎很奇怪一个张量对象。我已经通过 tensorflow api 文档和 stackoverflow 搜索了很长一段时间,似乎找不到比上面链接中提供的更简单的解决方案。这似乎特别奇怪,特别是考虑到 Theano 具有与 Tensor.set_subtensor() 等效的版本。我是否遗漏了什么,或者目前没有简单的方法可以通过 tensorflow api 做到这一点?

(2)如果有更简单的方法,是否可微分?

谢谢!

【问题讨论】:

  • 用numpy数组初始化张量值够吗?那我推荐一下方式。
  • 在最近的 Tensorflow 版本中,您可以使用类似 numpy 的切片来更新变量,如下所示:v[2:4].assign([1, 2]),其中vVariable。这能回答你的问题吗?
  • 感谢两位,感谢您的想法/cmets。不幸的是,这并不是我想要的……使用类似 numpy 的切片的更新变量就是这样,除了它仅适用于“变量”而不适用于“张量”。我重新设计了我的模型以避免对这个操作的明确需要,bc 似乎现实是张量对象在 tf 中是完全不可变的(与变量对象不同)。再次感谢您的想法!

标签: tensorflow


【解决方案1】:

我认为构建计算图需要张量的不变性;你不能让一个张量在不成为另一个张量的情况下更新它的一些值,否则在它之前的图表中将没有任何东西可以放入。 The same issue comes up in Autograd.

可以使用布尔掩码(使它们成为变量并使用assign,甚至在numpy 中定义它们之前)来做到这一点(但丑陋)。这将是可区分的,但实际上我会避免更新子张量。

如果你真的需要,我真的希望有更好的方法来做到这一点,但这里有一种使用tf.dynamic_stitchtf.setdiff1d 的一维方法:

def set_subtensor1d(a, b, slice_a, slice_b):
    # a[slice_a] = b[slice_b]
    a_range = tf.range(a.shape[0])
    _, a_from = tf.setdiff1d(a_range, a_range[slice_a])
    a_to = a_from
    b_from, b_to = tf.range(b.shape[0])[slice_b], a_range[slice_a]     
    return tf.dynamic_stitch([a_to, b_to],
                    [tf.gather(a, a_from),tf.gather(b, b_from)])

对于更高的维度,这可以通过滥用reshape 来概括(其中nd_slice could be implemented like this,但可能有更好的方法):

def set_subtensornd(a, b, slice_tuple_a, slice_tuple_b):
    # a[*slice_tuple_a] = b[*slice_tuple_b]
    a_range = tf.range(tf.reduce_prod(tf.shape(a)))
    a_idxed = tf.reshape(a_range, tf.shape(a))
    a_dropped = tf.reshape(nd_slice(a_idxed, slice_tuple_a), [-1])
    _, a_from = tf.setdiff1d(a_range, a_dropped)
    a_to = a_from
    b_range = tf.range(tf.reduce_prod(tf.shape(b)))
    b_idxed = tf.reshape(b_range, tf.shape(b))
    b_from = tf.reshape(nd_slice(b_idxed, slice_tuple_b), [-1])
    b_to = a_dropped
    a_flat, b_flat = tf.reshape(a, [-1]), tf.reshape(b, [-1])
    stitched = tf.dynamic_stitch([a_to, b_to],
                   [tf.gather(a_flat, a_from),tf.gather(b_flat, b_from)])
    return tf.reshape(stitched, tf.shape(a))

我不知道这会有多慢。我猜很慢。而且,除了在几个张量上运行它之外,我还没有对其进行太多测试。

【讨论】:

    猜你喜欢
    • 2021-08-01
    • 2018-06-25
    • 2021-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-31
    • 1970-01-01
    • 2022-01-24
    相关资源
    最近更新 更多