Tra*_*tal 13 python statistics entropy tensorflow
我有两个张量,prob_a并prob_b与形状[None, 1000],我想从计算KL散prob_a到prob_b.TensorFlow中是否有内置功能?我尝试过使用tf.contrib.distributions.kl(prob_a, prob_b)但它给出了:
prob_a
如果没有内置功能,那么什么是好的解决方法?
假设您的输入张量prob_a并且prob_b是沿第一轴总和为1的概率张量,您可以这样做:
def kl(x, y):
X = tf.distributions.Categorical(probs=x)
Y = tf.distributions.Categorical(probs=y)
return tf.distributions.kl_divergence(X, Y)
result = kl(prob_a, prob_b)
Run Code Online (Sandbox Code Playgroud)
一个简单的例子:
import numpy as np
import tensorflow as tf
a = np.array([[0.25, 0.1, 0.65], [0.8, 0.15, 0.05]])
b = np.array([[0.7, 0.2, 0.1], [0.15, 0.8, 0.05]])
sess = tf.Session()
print(kl(a, b).eval(session=sess)) # [0.88995184 1.08808468]
Run Code Online (Sandbox Code Playgroud)
你会得到相同的结果
np.sum(a * np.log(a / b), axis=1)
Run Code Online (Sandbox Code Playgroud)
但是,这个实现有点儿错误(在Tensorflow 1.8.0中检查).
如果您的概率为零a,例如,如果您尝试[0.8, 0.2, 0.0]而不是[0.8, 0.15, 0.05],则nan即使Kullback-Leibler定义0 * log(0 / b)应该归零,您也会得到.
为了缓解这个问题,我们应该添加一些小的数值常数.tf.distributions.kl_divergence(X, Y, allow_nan_stats=False)在这种情况下使用导致运行时错误也是谨慎的.
此外,如果有一些零b,您将获得inf该allow_nan_stats=False选项不会捕获的值,因此必须处理这些值.
小智 6
因为有softmax_cross_entropy_with_logits,所以不需要在KL上进行优化.
KL(prob_a, prob_b)
= Sum(prob_a * log(prob_a/prob_b))
= Sum(prob_a * log(prob_a) - prob_a * log(prob_b))
= - Sum(prob_a * log(prob_b)) + Sum(prob_a * log(prob_a))
= - Sum(prob_a * log(prob_b)) + const
= H(prob_a, prob_b) + const
Run Code Online (Sandbox Code Playgroud)
小智 5
我不确定为什么它没有实现,但也许有一个解决方法.KL分歧定义为:
KL(prob_a, prob_b) = Sum(prob_a * log(prob_a/prob_b))
另一方面,交叉熵H定义为:
H(prob_a, prob_b) = -Sum(prob_a * log(prob_b))
因此,如果您创建一个变量y = prob_a/prob_b,您可以通过调用负数来获得KL分歧H(proba_a, y).在Tensorflow表示法中,类似于:
KL = tf.reduce_mean(-tf.nn.softmax_cross_entropy_with_logits(prob_a, y))