使用 tf.where(或 np.where)以输入为条件随机绘制

Using tf.where (or np.where) to draw randomly conditional on an input

我有一个仅包含 1 和 0 的 TensorFlow 向量,例如 a = [0, 0, 0, 1, 0, 1],并且以 a 的值为条件,我想绘制新的随机值 0 或 1。如果值a 的值为 1,我想绘制一个新值,但如果 a 的值为 0,我不想管它。所以我试过了:

import tensorflow as tf
import tensorflow_probability as tfp
tfd = tfp.distributions

# random draw of zeros and ones
a = tfd.Binomial(total_count = 1.0, probs = 0.5).sample(6)

这给了我 <tf.Tensor: shape=(6,), dtype=float32, numpy=array([0., 0., 0., 1., 0., 1.], dtype=float32)> 然后如果我重绘

# redraw with a different probability if value is 1. in the original draw
b = tf.where(a == 1.0, tfd.Binomial(total_count = 1., probs = 0.5).sample(1), a)

我希望 tf.where 给我一个新向量 b 平均而言,一半的 1 变成 0 但它要么 returns [=] 的副本16=] 或全 0 的向量。示例输出将是 b = [0, 0, 0, 0, 0, 0]b = [0, 0, 0, 0, 0, 1]b = [0, 0, 0, 1, 0, 0]b = [0, 0, 0, 1, 0, 1] 之一。我当然可以只使用 b = tfd.Binomial(total_count = 1.0, probs = 0.25).sample(6) 但在我的特定情况下,原始向量的顺序很重要。

更一般的情况可能会使用不同的分布,因此无法轻松使用按位运算。例如

# random draw of normals
a = tfd.Normal(loc = 0., scale = 1.).sample(6)
# redraw with a different scale if value is greater than zero in the original draw
b = tf.where(a > 0, tfd.Normal(loc = 0., scale = 2.).sample(1), a)

方法 1:

未测试,但我认为中间参数应该是与原始参数匹配的张量。例如。 6 个元素:

首先,制作第二个长度相同的随机序列:

a2 = tfd.Binomial(total_count = 1.0, probs = 0.5).sample(6)

注意:如果您需要不同的概率,只需在创建 a2 时使用该概率即可。

prob = 0.3
a2 = tfd.Binomial(total_count = 1.0, probs = prob).sample(6)

然后:

b = tf.where(a == 1.0, a2, a)

解释:

a2 中的值与 a 为 0 的情况无关,并且在 a 为 1 的情况下平均为“概率”。


方法 2:

如果这不起作用,则需要将第一个参数映射到 [true, false, ..] 的张量:

def pos(n):
    return n > 0

cond = list(map(pos,a))   # I don't have TensorFlow handy; may need to replace `list` with appropriate function to create a Tensor.

b = tf.where(cond, a2, 0.0)

方法 3:

已测试。不使用 tf.where.

首先,制作第二个长度相同的随机序列:

a2 = tfd.Binomial(total_count = 1.0, probs = prob).sample(6)

然后结合两者,“按位与”对应的元素:

def and2(a, b):
    return (a & b)

b = list(map(and2, a, a2))

注意:也可以使用任何其他函数来组合两个相应的元素。

示例数据:

a = [0,0,1,1]
a2 = [0,1,0,1]

结果:

b = [0,0,0,1]

解释:

a2 中的值与 a 为 0 的情况无关,并且在 a 为 1 的情况下平均为“概率”。

tf.where 正在广播您的第二个参数,形状 [1] 值最多为六个向量 [6]。第二个值放在现有 1 的位置:1(在这种情况下输出匹配 a)或 0(在这种情况下全为零)。在每个站点为独立重采样值绘制六个样本。

考虑 tfd.Bernoulli 0/1 个样本。