作为一个项目的一部分,我有问题的梯度正态分布与张量流的概率。为此,我创建了一个正态分布,并抽取了一个样本。然后将该样本的对数概率输入优化器,以更新网络的权重。你知道吗
如果我得到某个常数的对数,我总是得到非零的梯度。不幸的是,我没有找到任何相关的帮助教程或类似的帮助来源。你知道吗
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)
输出:渐变[数组([0.],dtype=float32)]
当计算样本的梯度时,我希望得到非零梯度。相反,输出总是“0”
这是张量流概率实现重参数化梯度(又名“重参数化技巧”)的结果,实际上在某些情况下是正确的答案。让我告诉你这个答案是如何产生的。你知道吗
从具有某些位置和比例的正态分布生成样本的一种方法是,首先从标准正态分布生成样本(这通常是一些库提供的函数,例如TensorFlow中的
tf.random.normal
),然后对其进行移位和缩放。例如,假设tf.random.normal
的输出是z
。要从正态分布中获得样本x
,位置loc
和标度scale
,您需要执行: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()
),所以看起来梯度是正确的。你知道吗相关问题 更多 >
编程相关推荐