[英]Using toch log_prob to calculate the probability of selecting multiple values of the distribution itself
[英]tensorflow_probability: Gradients always zero when backpropagating the log_prob of a sample of a normal distribution
作为项目的一部分,我在处理具有 tensorflow_probability 的正态分布的梯度时遇到了问题。 为此,我创建了一个正态分布,其中抽取了一个样本。 然后将这个样本的 log_prob 送入优化器以更新网络的权重。
如果我得到某个常数的 log_prob,我总是得到非零梯度。 不幸的是,我在教程或类似的帮助来源中没有找到任何相关的帮助。
def get_log_prob(mu, std)
extracted_location = tf.squeeze(extracted_location)
normal = tfd.Normal(mu, scale=std)
samples = normal.sample(sample_shape=(1))
log_prob = normal.log_prob(samples)
return log_prob
const = tf.constant([0.1], dtype=np.float32)
log_prob = get_log_prob(const, 0.01)
grads = tf.gradients(log_prob, const)
with tf.Session() as sess:
gradients = sess.run([grads])
print('gradients', gradients)
输出:梯度 [array([0.], dtype=float32)]
如果在计算样本的梯度时,我希望得到非零梯度。 相反,输出始终为“0”。
这是 TensorFlow Probability 实现重新参数化梯度(又名“重新参数化技巧”)的结果,实际上是某些情况下的正确答案。让我向您展示0.
答案是如何产生的。
从具有某个位置和比例的正态分布生成样本的一种方法是首先从标准正态分布(这通常是某个库提供的函数,例如 TensorFlow 中的tf.random.normal
)生成样本,然后对其进行移位和缩放. 例如,假设tf.random.normal
的输出是z
。 要从具有 location loc
和 scale scale
的正态分布中获取样本x
,您可以执行以下操作: x = z * scale + loc
。
现在,如何计算正态分布下数字的概率密度值? 一种方法是反转该转换,以便您现在处理标准正态分布,然后计算那里的对数概率密度。 即log_prob(x) = log_prob_std_normal((x - loc) / scale) + f(scale)
( f(scale)
项来自转换中涉及的变量的变化,它的形式对于这个解释无关紧要) .
您现在可以将第一个表达式插入第二个表达式,您将得到log_prob(x) = log_prob_std_normal(z) + f(scale)
,即loc
完全取消! 因此, log_prob
相对于loc
的梯度为0.
. 这也解释了为什么您没有得到0.
如果您以常数评估对数概率:它将丢失用于创建样本的前向变换,并且您将获得一些(通常)非零梯度。
那么,这什么时候才是正确的行为呢? 当您计算分布参数相对于该分布下函数的期望的梯度时,重新参数化梯度是正确的。 计算这种期望的一种方法是进行蒙特卡罗近似,如下所示: tf.reduce_mean(g(dist.sample(N), axis=0)
。听起来这就是你正在做的事情(你的g()
是log_prob()
),所以看起来梯度是正确的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.