我认为张量的不变性是构造计算图所必需的;你不能让张量更新它的某些值而不成为另一个张量,否则在它之前没有任何东西可以放入图中。 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))
我不知道如何缓慢,这将是。我猜很慢。而且,除了在几个张量上运行之外,我还没有对它进行太多的测试。
您是否足够使用numpy数组初始化张量值?然后我推荐这种方式。 – Jin
在最新版本的Tensorflow中,您可以使用类似numpy的切片来更新变量,如下所示:'v [2:4] .assign([1,2])',其中'v'是'Variable'。这是否回答你的问题? –
谢谢你,欣赏这些想法/评论。不幸的是,我不是在寻找什么,尽管...使用numpy-like切片的更新变量就是它,除了它只适用于“变量”而不是“张量”。我重新设计了我的模型以避免明确需要这个操作,但现实看来,Tensor对象在tf中是完全不可变的(不像可变对象)。再次感谢您的想法! – joeliven