如何在 Python 中实现两个骰子概率的 KL 散度?

How can I implement the KL Divergence of two dice probabilities in Python?

我正在尝试从头开始在两个假想的骰子上实现 KL 散度,但我不确定它是否正确。
By 'how do I graph all distributions' 我想知道 KL 散度是一个数字还是一个分布?

进口

%matplotlib inline
import random
import numpy as np
import matplotlib. pyplot  as plt

我创建了空数组来存储大约 5500 卷两个不同的假想骰子。
骰子 p 以相同的概率掷出 1-6。
Die q 90% 的时间掷出 1-4,只有 10% 的时间掷出 5 或 6。 (当然,工作模具预计有六分之一的时间掷出 1-6。

q = []
p = []
for z in range(5000):
    if random.random() < 0.1:
        q.append(random.randint(5, 6))
        p.append(random.randint(1, 6))
    q.append(random.randint(1, 4))
    p.append(random.randint(1, 6))

die p 和 die q 的分布示例。

在这里,我随机抽取骰子数组的样本,并对 p 选择除以 q 选择的对数进行积分。这是我认为我无法理解的地方,因为我不知道我是否应该进行求和或积分。当我做一个总结时,我得到了一个巨大的数字。下面我想我可能有正确的集成,但我不知道我是否需要它,因为我正在处理一组有限的骰子。
对于 dx,我使用 12 除以两个数组的长度。 12 是可能的骰子数,两个数组的总长度是从单个掷骰子中读取的每个读数的总数。

kl_num = 0
both_len = len(q)+len(p)
for i in range(both_len):
    q_selection = q[random.randint(0, len(q)-1)]
    p_selection = p[random.randint(0, len(p)-1)]
    kl_num += p_selection * np.log(p_selection / q_selection) * 12 / both_len

$D_{KL} (P || Q) = \int P(x) log(P(x)/Q(x)) dx $

kl_num 中存储的数字通常约为 22。这让我想到了问题的 B 部分,关于如何绘制图表或我如何知道这是否正确。

谢谢。

为了计算两个分布的KL,你需要有每个点的概率。我认为在你的 KL 公式中,有一个错误(请再次检查)。例如,对于您提供的直方图,如果我们将您提供的 直方图 视为分布(您绝对应该考虑它们的分布)。您提供的两个分布的 KL 是 大约 计算为:

1000* log(1200/900) +1300* log(1300/950) +1200*log(1200/900) + 1100*log(1100/900)+250*log(250/900)+ 260*log(260/950)

KL 散度中的概率不是实际概率。
这包含一个计算两个分布概率的循环,它们在 KL 散度方程中被调用。

%matplotlib inline
import random
import numpy as np
import matplotlib. pyplot  as plt  

q = []
p = []
for z in range(5000):
    if random.random() < 0.1:
        q.append(random.randint(5, 6))
        p.append(random.randint(1, 6))
    q.append(random.randint(1, 4))
    p.append(random.randint(1, 6))

def probs(array):
    fo = []
    count = 0
    for i in range(6):
        sh = array.count(i+1) / np.sum(array)
        fo.append(sh)
        count += sh
        factor = 1 / count
    return [factor * z for z in fo]

KL = 0
for x in range(6):
    KL += probs(p)[x] * np.log(probs(p)[x] / probs(q)[x])
print(KL)