张量流索引是如何工作的
how does tensorflow indexing work
我无法理解 tensorflow 的基本概念。张量 read/write 操作的索引如何工作?为了具体说明,如何将以下 numpy 示例转换为 tensorflow(对数组、索引和分配的值使用张量):
x = np.zeros((3, 4))
row_indices = np.array([1, 1, 2])
col_indices = np.array([0, 2, 3])
x[row_indices, col_indices] = 2
x
输出:
array([[ 0., 0., 0., 0.],
[ 2., 0., 2., 0.],
[ 0., 0., 0., 2.]])
...和...
x[row_indices, col_indices] = np.array([5, 4, 3])
x
输出:
array([[ 0., 0., 0., 0.],
[ 5., 0., 4., 0.],
[ 0., 0., 0., 3.]])
...最后...
y = x[row_indices, col_indices]
y
输出:
array([ 5., 4., 3.])
有 github 个问题 #206 可以很好地支持这一点,同时你必须求助于冗长的解决方法
第一个例子可以用tf.select
来完成,它通过从一个或另一个中选择每个元素来组合两个相同形状的张量
tf.reset_default_graph()
row_indices = tf.constant([1, 1, 2])
col_indices = tf.constant([0, 2, 3])
x = tf.zeros((3, 4))
sess = tf.InteractiveSession()
# get list of ((row1, col1), (row2, col2), ..)
coords = tf.transpose(tf.pack([row_indices, col_indices]))
# get tensor with 1's at positions (row1, col1),...
binary_mask = tf.sparse_to_dense(coords, x.get_shape(), 1)
# convert 1/0 to True/False
binary_mask = tf.cast(binary_mask, tf.bool)
twos = 2*tf.ones(x.get_shape())
# make new x out of old values or 2, depending on mask
x = tf.select(binary_mask, twos, x)
print x.eval()
给予
[[ 0. 0. 0. 0.]
[ 2. 0. 2. 0.]
[ 0. 0. 0. 2.]]
第二个可以用 scatter_update
完成,除了 scatter_update
只支持线性索引并且适用于变量。所以你可以创建一个临时变量并像这样使用重塑。 (为避免变量,您可以使用 dynamic_stitch
,请参阅结尾)
# get linear indices
linear_indices = row_indices*x.get_shape()[1]+col_indices
# turn 'x' into 1d variable since "scatter_update" supports linear indexing only
x_flat = tf.Variable(tf.reshape(x, [-1]))
# no automatic promotion, so make updates float32 to match x
updates = tf.constant([5, 4, 3], dtype=tf.float32)
sess.run(tf.initialize_all_variables())
sess.run(tf.scatter_update(x_flat, linear_indices, updates))
# convert back into original shape
x = tf.reshape(x_flat, x.get_shape())
print x.eval()
给予
[[ 0. 0. 0. 0.]
[ 5. 0. 4. 0.]
[ 0. 0. 0. 3.]]
最后第三个例子已经支持gather_nd
,你写
print tf.gather_nd(x, coords).eval()
得到
[ 5. 4. 3.]
编辑,5 月 6 日
更新 x[cols,rows]=newvals
可以在不使用变量(在会话 运行 调用之间占用内存)的情况下通过使用 select
和 sparse_to_dense
来完成,它采用稀疏值向量, 或依靠 dynamic_stitch
sess = tf.InteractiveSession()
x = tf.zeros((3, 4))
row_indices = tf.constant([1, 1, 2])
col_indices = tf.constant([0, 2, 3])
# no automatic promotion, so specify float type
replacement_vals = tf.constant([5, 4, 3], dtype=tf.float32)
# convert to linear indexing in row-major form
linear_indices = row_indices*x.get_shape()[1]+col_indices
x_flat = tf.reshape(x, [-1])
# use dynamic stitch, it merges the array by taking value either
# from array1[index1] or array2[index2], if indices conflict,
# the later one is used
unchanged_indices = tf.range(tf.size(x_flat))
changed_indices = linear_indices
x_flat = tf.dynamic_stitch([unchanged_indices, changed_indices],
[x_flat, replacement_vals])
x = tf.reshape(x_flat, x.get_shape())
print x.eval()
我无法理解 tensorflow 的基本概念。张量 read/write 操作的索引如何工作?为了具体说明,如何将以下 numpy 示例转换为 tensorflow(对数组、索引和分配的值使用张量):
x = np.zeros((3, 4))
row_indices = np.array([1, 1, 2])
col_indices = np.array([0, 2, 3])
x[row_indices, col_indices] = 2
x
输出:
array([[ 0., 0., 0., 0.],
[ 2., 0., 2., 0.],
[ 0., 0., 0., 2.]])
...和...
x[row_indices, col_indices] = np.array([5, 4, 3])
x
输出:
array([[ 0., 0., 0., 0.],
[ 5., 0., 4., 0.],
[ 0., 0., 0., 3.]])
...最后...
y = x[row_indices, col_indices]
y
输出:
array([ 5., 4., 3.])
有 github 个问题 #206 可以很好地支持这一点,同时你必须求助于冗长的解决方法
第一个例子可以用tf.select
来完成,它通过从一个或另一个中选择每个元素来组合两个相同形状的张量
tf.reset_default_graph()
row_indices = tf.constant([1, 1, 2])
col_indices = tf.constant([0, 2, 3])
x = tf.zeros((3, 4))
sess = tf.InteractiveSession()
# get list of ((row1, col1), (row2, col2), ..)
coords = tf.transpose(tf.pack([row_indices, col_indices]))
# get tensor with 1's at positions (row1, col1),...
binary_mask = tf.sparse_to_dense(coords, x.get_shape(), 1)
# convert 1/0 to True/False
binary_mask = tf.cast(binary_mask, tf.bool)
twos = 2*tf.ones(x.get_shape())
# make new x out of old values or 2, depending on mask
x = tf.select(binary_mask, twos, x)
print x.eval()
给予
[[ 0. 0. 0. 0.]
[ 2. 0. 2. 0.]
[ 0. 0. 0. 2.]]
第二个可以用 scatter_update
完成,除了 scatter_update
只支持线性索引并且适用于变量。所以你可以创建一个临时变量并像这样使用重塑。 (为避免变量,您可以使用 dynamic_stitch
,请参阅结尾)
# get linear indices
linear_indices = row_indices*x.get_shape()[1]+col_indices
# turn 'x' into 1d variable since "scatter_update" supports linear indexing only
x_flat = tf.Variable(tf.reshape(x, [-1]))
# no automatic promotion, so make updates float32 to match x
updates = tf.constant([5, 4, 3], dtype=tf.float32)
sess.run(tf.initialize_all_variables())
sess.run(tf.scatter_update(x_flat, linear_indices, updates))
# convert back into original shape
x = tf.reshape(x_flat, x.get_shape())
print x.eval()
给予
[[ 0. 0. 0. 0.]
[ 5. 0. 4. 0.]
[ 0. 0. 0. 3.]]
最后第三个例子已经支持gather_nd
,你写
print tf.gather_nd(x, coords).eval()
得到
[ 5. 4. 3.]
编辑,5 月 6 日
更新 x[cols,rows]=newvals
可以在不使用变量(在会话 运行 调用之间占用内存)的情况下通过使用 select
和 sparse_to_dense
来完成,它采用稀疏值向量, 或依靠 dynamic_stitch
sess = tf.InteractiveSession()
x = tf.zeros((3, 4))
row_indices = tf.constant([1, 1, 2])
col_indices = tf.constant([0, 2, 3])
# no automatic promotion, so specify float type
replacement_vals = tf.constant([5, 4, 3], dtype=tf.float32)
# convert to linear indexing in row-major form
linear_indices = row_indices*x.get_shape()[1]+col_indices
x_flat = tf.reshape(x, [-1])
# use dynamic stitch, it merges the array by taking value either
# from array1[index1] or array2[index2], if indices conflict,
# the later one is used
unchanged_indices = tf.range(tf.size(x_flat))
changed_indices = linear_indices
x_flat = tf.dynamic_stitch([unchanged_indices, changed_indices],
[x_flat, replacement_vals])
x = tf.reshape(x_flat, x.get_shape())
print x.eval()