Tensorflow:计算标签的逆计数

时间:2018-11-27 10:14:56

标签: python tensorflow

我有一个整数(b,n)的张量labels,其值在[0,1,2,3,4,5]中。 我想创建一个形状(b,n)的张量weights,在位置(i,j)携带整数labels[i,j]在标签中出现的次数的倒数。

工作示例代码:

import tensorflow as tf
import numpy as np
tf.InteractiveSession()
labels=tf.convert_to_tensor(np.array([[1,0,0,1,2,4],[2,2,2,4,2,1]]), dtype=tf.int32)
weights=tf.ones_like(labels, dtype=tf.float32)
bc=tf.bincount(labels, minlength=6, maxlength=6)
for i in range(6):
    cur_count = 1.0/(1e-10+tf.cast(bc[i], tf.float32))
    count_tensor = tf.ones_like(labels, dtype=tf.float32)*cur_count
    weights = tf.where(tf.equal(labels,i), count_tensor, weights)
weights.eval()
# array([[0.3333, 0.5, 0.5, 0.3333, 0.2, 0.5],
#        [0.2, 0.2, 0.2, 0.5, 0.2, 0.3333]], dtype=float32)

例如,标签1labels张量中出现3次,因此在weights中,值1/3出现在每个位置,其中1labels中。

现在我对这段代码不满意的是tf.bincount在我的Tensorflow版本(1.4.0)中无法在GPU上运行,并且我无法更新。 另外,我不确定张量流如何处理for循环以及由此产生多少开销。

我想我的问题有一个更优雅的解决方案。有什么想法吗?

1 个答案:

答案 0 :(得分:3)

关于循环,您可以将其替换为对tf.gather的调用:

import tensorflow as tf
import numpy as np

tf.InteractiveSession()
labels = tf.convert_to_tensor(
    np.array([[1, 0, 0, 1, 2, 4], [2, 2, 2, 4, 2, 1]]), dtype=tf.int32)
bc = tf.bincount(labels, minlength=6, maxlength=6)
weights = tf.gather(1.0 / (1e-10 + tf.cast(bc, tf.float32)), labels)
print(weights.eval())

输出:

[[0.33333334 0.5        0.5        0.33333334 0.2        0.5       ]
 [0.2        0.2        0.2        0.5        0.2        0.33333334]]

关于tf.bincount仅限于CPU,目前似乎并非如此。实际上,since v1.5.0似乎已经提供了GPU实现。

如果您想要其他实现,可以执行以下操作:

import tensorflow as tf
import numpy as np

tf.InteractiveSession()
labels = tf.convert_to_tensor(
    np.array([[1, 0, 0, 1, 2, 4], [2, 2, 2, 4, 2, 1]]), dtype=tf.int32)
eq = tf.equal(labels[:, :, tf.newaxis], tf.range(6, dtype=labels.dtype))
bc = tf.reduce_sum(tf.cast(eq, tf.float32), axis=[0, 1])
weights = tf.gather(1.0 / (1e-10 + tf.cast(bc, tf.float32)), labels)
print(weights.eval())
# Same output

但是tf.bincount可能比这更有效。