首页 > 解决方案 > 如何在 Python 语言中重现以下概率函数?

问题描述

我有一个任务,我有一个特定值的列表:l = ["alpha", "beta", "beta", "alpha", "gamma", "alpha", "alpha"]. 我有一个公式用于计算此列表中的一种概率,如下所示(如果列表中有许多不同的值,则概率很高,如果值很少,则概率很低):

$ p = - \sum_{i=1}^m f_i log_m f_i $

其中m是列表的长度,$f_i$ 是列表中第 i 个元素的频率。

我想在 Python 中使用以下代码对此进行编码:

from math import log
from collections import Counter

-sum([loc*log(loc, len(set(l))) for loc in Counter(l).values()])

但我不知何故怀疑这不是正确的方法。有更好的主意吗?另外:我不明白公式中的负号,这是什么解释?

标签: pythonformulaprobability

解决方案


虽然 numpy 数组是更好的解决方案,但如果您不想使用 numpy:

  1. 如果您保存计数器并使用 len(Counter) 而不是 len(set(l)) 会更好,这样您就不会在每次迭代中重新计算。len(Counter) 与 len(set(l)) 相同,但不会在每次迭代中重新计算(我假设您使用 cpython3.x)
  2. 如果你没有得到想要的结果,那么你的公式可能是错误的
  3. 在您的代码中,您使用 len(set(l)) 而不是 len(l) 并且您迭代频率,而不是您在公式中描述的列表。
  4. 您不需要将表达式包含在列表中的 sum 内,因为您只需要对其进行一次迭代(生成器表达式与列表推导式

编辑:至于为什么你得到一个否定的结果,这是预期的你总和f[i] * log(f[i])> = 0

  • f[i]>= 1:列表第 i 个元素的频率
  • log(f[i])>= 0 因为f[i]>= 1:任何基数中每个频率的对数(基数无关紧要)。

然后采取否定的态度。结果将始终小于或等于 0。

from math import log
from collections import Counter

l = ["alpha", "beta", "beta", "alpha", "gamma", "alpha", "alpha"]
f = Counter(l)
# This is from your code
p1 = -sum(f[e] * log(f[e], len(f)) for e in f)
# This is from your formula
p2 = -sum(f[e] * log(f[e], len(l)) for e in l)
print(p1, p2)


推荐阅读