我有一个K(x_i,y_i)对的列表,其中0 <= x_i&lt; X和0 <= y_i&lt; Y表示形状的张量[K,2]。
我想创建一个形状[K,X,Y]的张量T,其中如果x = x_i且y = y_i则T [i,x,y] = 1,否则为0。
我知道对于索引列表我可以使用tf.one_hot,但不确定我是否可以在这里重用它?类似于tf.one_hot(对,深度=(X,Y))
答案 0 :(得分:0)
从this SO post开始,我们可以在numpy
中轻松完成此操作:
(np.arange(a.max()) == a[...,None]-1).astype(int)
完全使用这个技巧,现在我们只需将其移植到tensorflow
:
# for the numpy, full credit to @Divakar and https://stackoverflow.com/questions/34987509/tensorflow-max-of-a-tensor-along-an-axis
print('first an awesome way to do it in numpy...')
a = np.array([[1,2,4],[3,1,0]])
print((np.arange(a.max()) == a[...,None]-1).astype(int))
# porting this to tensorflow...
print('\nnow in tensorflow...')
b = tf.constant([[1,2,4],[3,1,0]])
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
print(sess.run(tf.cast(tf.equal(tf.range(tf.reduce_max(b)),tf.reshape(b,[2,3,1])-1),tf.int32)))
返回:
first an awesome way to do it in numpy...
[[[1 0 0 0]
[0 1 0 0]
[0 0 0 1]]
[[0 0 1 0]
[1 0 0 0]
[0 0 0 0]]]
now in tensorflow...
[[[1 0 0 0]
[0 1 0 0]
[0 0 0 1]]
[[0 0 1 0]
[1 0 0 0]
[0 0 0 0]]]
这很有趣。
答案 1 :(得分:0)
我认为最好的解决方案是使用tf.sparse_to_dense
。例如,如果我们希望将它们放在10x8矩阵的(6,2),(3,4),(4,5)位置:
indices = sorted([[6,2],[3,4],[4,5]])
one_hot_encoded = tf.sparse_to_dense(sparse_indices=indices, output_shape=[10,8], sparse_values=1)
with tf.Session() as session:
tf.global_variables_initializer().run()
print(one_hot_encoded.eval())
这将返回以下内容:
[[0. 0. 0. 0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 1. 0.]
[0. 0. 0. 0. 0. 0. 0. 0.]
[0. 0. 0. 1. 0. 0. 0. 0.]
[0. 0. 0. 0. 1. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 0.]]
此外,输入(例如索引)可能是tf.Variable对象,不需要保持不变。
它有两个限制,即必须对索引进行排序(因此,上面的sorted
)并且不能重复。您也可以直接使用tf.one_hot。在这种情况下,您需要将索引作为所有x
之前和之后的所有y
,即list(zip(*indices))
的两个向量。然后一个人可以做:
new_indices = list(zip(*indices))
# one of the following: the first one is for xy index convention:
flat_indices = new_indices[1] * depth[1] + new_indices[0]
# this other for ij convention:
# flat_indices = new_indices[0] * depth[1] + new_indices[1]
# Apply tf.one_hot to the flattened vector, then sum along the newly created dimension
one_hot_flat = tf.reduce_sum(tf.one_hot(flat_indices, depth=np.prod(im_size)), axis=0)
# Finally reshape
one_hot_encoded = tf.reshape(oh, im_size)
with tf.Session() as session:
tf.global_variables_initializer().run()
print(one_hot_encoded.eval())
这与上面的返回相同。但是,索引不需要排序,并且可以重复(在这种情况下,对应的条目将是出现的次数;对于到处都是简单的“ 1”,请将tf.reduce_sum
替换为{{1} }。这也支持变量。
但是,对于大索引/深度,内存消耗可能是一个问题。它创建一个临时tf.reduce_max
张量,其中N x W x H
是索引元组的数量,可能会出现问题。因此,在可能的情况下,第一种解决方案可能是更可取的。
实际上,如果可以使用稀疏张量就可以了,那么最有效利用内存的方法可能就是:
N
运行时,这将返回更神秘的内容:
sparse = tf.SparseTensor(indices=indices, values=[1]*len(indices), dense_shape=[10, 8])