python - 如何在 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()])
但我不知何故怀疑这不是正确的方法。有更好的主意吗?另外:我不明白公式中的负号,这是什么解释?
解决方案
虽然 numpy 数组是更好的解决方案,但如果您不想使用 numpy:
- 如果您保存计数器并使用 len(Counter) 而不是 len(set(l)) 会更好,这样您就不会在每次迭代中重新计算。len(Counter) 与 len(set(l)) 相同,但不会在每次迭代中重新计算(我假设您使用 cpython3.x)
- 如果你没有得到想要的结果,那么你的公式可能是错误的
- 在您的代码中,您使用 len(set(l)) 而不是 len(l) 并且您迭代频率,而不是您在公式中描述的列表。
- 您不需要将表达式包含在列表中的 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)
推荐阅读
- python-3.x - 考虑两列计算平均值
- sql - 如果我们发送 null 或 "" 值,如何避免 Where 子句条件
- sql - 在 Ireports 设计器中计算在场、缺席和总体百分比的学生人数
- excel - VBA图表x轴不适合
- javascript - 根据网址的页脚高度?
- c# - 网络流不写入数据
- android - 文本输入内的 ImageButon 编辑文本而不会丢失浮动标签
- ios - 在文本字段中的图标和文本之间添加空格
- ballerina - 在 Ballerina 中对数组进行切片
- python - 连接中断:在 Heroku 上向 Django 发送请求时 IncompleteRead(0 字节读取)