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

joe*_*ven 9 tensorflow

这个问题的两个部分:

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

在Tensor中调整单值 - TensorFlow 以及 如何在Tensorflow中更新2D张量的子集?

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

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

谢谢!

Gav*_*ray 1

我认为张量的不变性是构建计算图所必需的;你不能让一个张量更新它的一些值而不成为另一个张量,否则在它之前的图中将没有任何内容。Autograd 中也出现了同样的问题

可以使用布尔掩码来做到这一点(但很难看)(使它们成为变量并使用assign,或者甚至在 numpy 中预先定义它们)。这将是可微分的,但实际上我会避免更新子张量。

如果你真的必须这样做,我真的希望有更好的方法来做到这一点,但这里有一种在一维中使用的方法tf.dynamic_stitch如果你真的必须这样做,我真的希望有更好的方法来做到这一点,但这里有一种在一维中使用和tf.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)])
Run Code Online (Sandbox Code Playgroud)

对于更高的维度,这可以通过滥用来推广reshape (其中nd_slice可以像这样实现,但可能有更好的方法):

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))
Run Code Online (Sandbox Code Playgroud)

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