这个问题的两个部分:
(1)更新张量流中张量子集的最佳方法是什么?我已经看到了几个相关的问题:
Adjust Single Value within Tensor -- TensorFlow 和 How 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)如果有更简单的方法,它是否可以区分?
谢谢!
答案 0 :(得分:1)
我认为构建计算图需要Tensors的不变性;你不能让Tensor更新它的一些值而不会成为另一个Tensor,或者在它之前没有任何东西放在图中。 The same issue comes up in Autograd
使用布尔掩码可以做到这一点(但很难看)(使它们成为变量并使用assign
,甚至可以在numpy之前定义它们)。这是可以区分的,但实际上我不必更新子传感器。
如果你真的需要,我真的希望有更好的方法来做到这一点,但是这里有一种方法可以使用tf.dynamic_stitch
和tf.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))
我不知道这会有多慢。我觉得很慢。而且,除了在几个张量上运行它之外,我还没有测试过它。