我发现Tensorflow提供scatter_update()
来为0维度中的张量切片赋值。例如,如果张量T
是三维的,我可以将值v[1, :, :]
指定给T[i, :, :]
。
a = tf.Variable(tf.zeros([10,36,36]))
value = np.ones([1,36,36])
d = tf.scatter_update(a,[0],value)
with tf.Session() as sess:
sess.run(tf.initialize_all_variables())
print a.eval()
sess.run(d)
print a.eval()
但是如何将值v[1,1,:]
分配给T[i,j,:]
?
a = tf.Variable(tf.zeros([10,36,36]))
value1 = np.random.randn(1,1,36)
e = tf.scatter_update(a,[0],value1) #Error
with tf.Session() as sess:
sess.run(tf.initialize_all_variables())
print a.eval()
sess.rum(e)
print a.eval()
TF提供的其他功能还是一种简单的方法吗?
答案 0 :(得分:34)
目前,您可以在TensorFlow中为变量执行切片分配。它没有特定的命名功能,但您可以选择一个切片并在其上调用assign
:
my_var = my_var[4:8].assign(tf.zeros(4))
首先,请注意(在查看the documentation之后)assign
的返回值,即使应用于切片,也始终是对整体的引用应用更新后,em>变量。
编辑:以下信息已弃用,不精确或始终错误。事实是assign
的返回值是一个可以很容易使用的张量,并且已经将依赖项合并到赋值中,因此简单地评估它或在进一步的操作中使用它将确保它在不需要显式的情况下执行tf.control_dependencies
阻止。
另请注意,这只会将赋值操作添加到图形中,但除非显式执行或设置为某些其他操作的依赖项,否则不会运行它。一个好的做法是在tf.control_dependencies
上下文中使用它:
with tf.control_dependencies([my_var[4:8].assign(tf.zeros(4))]):
my_var = tf.identity(my_var)
您可以在TensorFlow问题#4638中详细了解它。
答案 1 :(得分:8)
我相信您需要的是ticket #206中讨论的assign_slice_update
。 但现在还没有。
更新:现在已经实现了。请参阅jdehesa的回答:https://stackoverflow.com/a/43139565/6531137
在assign_slice_update
(或scatter_nd()
)可用之前,您可以构建所需行的块,其中包含您不想修改的值以及要更新的所需值,如下所示:
import tensorflow as tf
a = tf.Variable(tf.ones([10,36,36]))
i = 3
j = 5
# Gather values inside the a[i,...] block that are not on column j
idx_before = tf.concat(1, [tf.reshape(tf.tile(tf.Variable([i]), [j]), [-1, 1]), tf.reshape(tf.range(j), [-1, 1])])
values_before = tf.gather_nd(a, idx_before)
idx_after = tf.concat(1, [tf.reshape(tf.tile(tf.Variable([i]), [36-j-1]), [-1, 1]), tf.reshape(tf.range(j+1, 36), [-1, 1])])
values_after = tf.gather_nd(a, idx_after)
# Build a subset of tensor `a` with the values that should not be touched and the values to update
block = tf.concat(0, [values_before, 5*tf.ones([1, 36]), values_after])
d = tf.scatter_update(a, i, block)
with tf.Session() as sess:
sess.run(tf.initialize_all_variables())
sess.run(d)
print(a.eval()[3,4:7,:]) # Print a subset of the tensor to verify
该示例生成一个张量并执行a[i,j,:] = 5
。大部分复杂性在于获取我们不想修改的值,a[i,~j,:]
(否则scatter_update()
将替换这些值。)
如果您想按照要求执行T[i,k,:] = a[1,1,:]
,则需要将上一个示例中的5*tf.ones([1, 36])
替换为tf.gather_nd(a, [[1, 1]])
。
另一种方法是从tf.select()
创建一个掩码,并将其分配给变量,如下所示:
import tensorflow as tf
a = tf.Variable(tf.zeros([10,36,36]))
i = tf.Variable([3])
j = tf.Variable([5])
# Build a mask using indices to perform [i,j,:]
atleast_2d = lambda x: tf.reshape(x, [-1, 1])
indices = tf.concat(1, [atleast_2d(tf.tile(i, [36])), atleast_2d(tf.tile(j, [36])), atleast_2d(tf.range(36))])
mask = tf.cast(tf.sparse_to_dense(indices, [10, 36, 36], 1), tf.bool)
to_update = 5*tf.ones_like(a)
out = a.assign( tf.select(mask, to_update, a) )
with tf.Session() as sess:
sess.run(tf.initialize_all_variables())
sess.run(out)
print(a.eval()[2:5,5,:])
内存方面效率可能较低,因为它需要两倍的内存来处理a
- 如to_update
变量,但您可以轻松修改最后一个示例以获得渐变保留操作来自tf.select(...)
节点。您可能还有兴趣查看其他StackOverflow问题:Conditional assignment of tensor values in TensorFlow。
那些不雅的扭曲应该被替换为对正确的TensorFlow函数的调用,因为它变得可用。
答案 2 :(得分:1)
tf.scatter_update
可以修改第一维中的张量。如文档中所述,
指数:A Tensor。必须是以下类型之一:int32,int64。指数的第一个维度的张量。
您可以使用scatter_nd_update
功能来执行您想要的操作。如下图所示,我已经测试过了。
a = tf.Variable(tf.zeros([10,36,36]))
value1 = np.random.randn(1,36)
e = tf.scatter_nd_update(a,[[0,1]],value1)
init= tf.global_variables_initializer()
sess.run(init)
print(a.eval())
sess.run(e)
答案 3 :(得分:0)
TF2的答案:
不幸的是,在Tensorflow 2(TF2)中仍然没有优雅的方法来做到这一点。
我发现的最好方法是取消分配然后重新堆叠:
x = tf.random.uniform(shape=(5,))
new_val = 7
y = tf.unstack(x)
y[2] = new_val
x_updated = tf.stack(y)