如何在张量流中为张量的子集赋值?

时间:2016-10-27 23:23:24

标签: tensorflow

这个问题的两个部分:

(1)更新张量流中张量子集的最佳方法是什么?我已经看到了几个相关的问题:

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

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

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

谢谢!

1 个答案:

答案 0 :(得分:1)

我认为构建计算图需要Tensors的不变性;你不能让Tensor更新它的一些值而不会成为另一个Tensor,或者在它之前没有任何东西放在图中。 The same issue comes up in Autograd

使用布尔掩码可以做到这一点(但很难看)(使它们成为变量并使用assign,甚至可以在numpy之前定义它们)。这是可以区分的,但实际上我不必更新子传感器。

如果你真的需要,我真的希望有更好的方法来做到这一点,但是这里有一种方法可以使用tf.dynamic_stitchtf.setdiff1d在1D中完成:

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))

我不知道这会有多慢。我觉得很慢。而且,除了在几个张量上运行它之外,我还没有测试过它。