tensorflowrandommultinomial

Sampling without replacement from a given non-uniform distribution in TensorFlow


I'm looking for something similar to numpy.random.choice(range(3),replacement=False,size=2,p=[0.1,0.2,0.7])
in TensorFlow.

The closest Op to it seems to be tf.multinomial(tf.log(p)) which takes logits as input but it can't sample without replacement. Is there any other way to do sampling from a non-uniform distribution in TensorFlow?

Thanks.


Solution

  • You could just use tf.py_func to wrap numpy.random.choice and make it available as a TensorFlow op:

    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]}))
    

    You can specify the numpy seed as usual:

    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]}))
    

    would print:

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