在TensorFlow中从给定的非均匀分布中进行无替换抽样

9
我正在寻找类似于numpy.random.choice(range(3),replacement=False,size=2,p=[0.1,0.2,0.7])的东西,在TensorFlow中。与之最接近的Op似乎是tf.multinomial(tf.log(p)),它以logits作为输入,但无法进行无重复抽样。是否有其他方法在TensorFlow中从非均匀分布中进行采样?谢谢。
2个回答

4

是的,有解决方法。请参见此处此处了解一些背景信息。解决方案如下:

z = -tf.log(-tf.log(tf.random_uniform(tf.shape(p),0,1))) 
_, indices = tf.nn.top_k(tf.log(p) + z, size)

2

您可以使用tf.py_funcnumpy.random.choice进行封装,以便作为TensorFlow操作可用:

a = tf.placeholder(tf.float32)
size = tf.placeholder(tf.int32)
replace = tf.placeholder(tf.bool)
p = tf.placeholder(tf.float32)

y = tf.py_func(np.random.choice, [a, size, replace, p], tf.float32)

with tf.Session() as sess:
    print(sess.run(y, {a: range(3), size: 2, replace:False, p:[0.1,0.2,0.7]}))

您可以像平常一样指定numpy种子:

np.random.seed(1)
print(sess.run(y, {a: range(3), size: 2, replace:False, p:[0.1,0.2,0.7]}))
print(sess.run(y, {a: range(3), size: 2, replace:False, p:[0.1,0.2,0.7]}))
print(sess.run(y, {a: range(3), size: 2, replace:False, p:[0.1,0.2,0.7]}))
np.random.seed(1)
print(sess.run(y, {a: range(3), size: 2, replace:False, p:[0.1,0.2,0.7]}))
print(sess.run(y, {a: range(3), size: 2, replace:False, p:[0.1,0.2,0.7]}))
print(sess.run(y, {a: range(3), size: 2, replace:False, p:[0.1,0.2,0.7]}))
np.random.seed(1)
print(sess.run(y, {a: range(3), size: 2, replace:False, p:[0.1,0.2,0.7]}))

将会输出:

[ 2.  0.]
[ 2.  1.]
[ 0.  1.]
[ 2.  0.]
[ 2.  1.]
[ 0.  1.]
[ 2.  0.]

1
使用 tf.py_func 是可怕的,因为调用python操作会极大地减慢计算速度。特别是当你使用GPU时,利用率可能从100%降至5%,具体取决于任务。由于我认为没有新的操作可以做到这一点,最好的方法是编写自定义的c++操作。但是您可以通过例如迭代地从数组中采样一个元素,并通过类似于 tf.gather 的方式删除该元素来进行黑客攻击。 - user2781994

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接