【问题标题】:Normalize Small Probabilities in Python规范化 Python 中的小概率
【发布时间】:2014-11-14 03:23:25
【问题描述】:

我有一个概率列表,我需要将其标准化为等于 1.0。
例如probs = [0.01,0.03,0.005]

我意识到这是通过将每个概率除以probs 的总和来完成的。但是,如果概率变得非常小,Python 会告诉我sum(probs)=0.0。我知道这是一个下溢问题。我想我应该使用每个概率的对数。我该怎么做?

【问题讨论】:

  • 你想让它们在 [1-0] 之间吗?这就是规范化的意思。
  • 我认为他想将每个值乘以某个常数,使sum(probs) 等于一。
  • 您确定这不是打印问题吗?如果数组中的各个元素不完全为零,则总和应该是机器可表示的,但可能您的打印选项仅将其显示为零。

标签: python probability


【解决方案1】:

即使是非常小的浮点值的总和也永远不会真正为 0;它们可能接近为零,但永远不可能完全为零。

只需将 1 除以它们的总和,然后将概率乘以该因子:

def normalize(probs):
    prob_factor = 1 / sum(probs)
    return [prob_factor * p for p in probs]

当然,某些概率可能占总和的非常小的百分比,并且该百分比可能接近于零。但这只是意味着在归一化时,您最终可能会得到非常接近零的归一化概率,或者如果小于可表示的最小浮点值,则等于零。后者只有在列表中的概率比其他概率小得多以至于它们不再代表任何接近将要发生的事情时才会发生。

演示:

>>> def normalize(probs):
...     prob_factor = 1 / sum(probs)
...     return [prob_factor * p for p in probs]
... 
>>> normalize([0.0000000001,0.000000000003,0.000000000000005])
[0.9708266589000533, 0.029124799767001597, 4.854133294500266e-05]

还有极端情况:

>>> import sys
>>> normalize([sys.float_info.max, sys.float_info.min])
[0.9999999999999999, 0.0]
>>> normalize([sys.float_info.max, sys.float_info.min])[-1] == 0
True

【讨论】:

  • 谢谢。我不确定为什么这仍然对我不起作用——这是有道理的。我怀疑零在我的代码中更深。
【解决方案2】:

您始终可以使用比例因子来避免下溢问题,无论是手动输入还是自动计算,例如:

import math
no_z = ([x for x in probs if x > 0.0])
if len(no_z) == 0:
   print "Unable to calculate with 0.0 as all the probabilities"
order = int(-math.log10(min(no_z)))
if order > 0:
   order = 0
sf = 10**order
scaled = [x * sf for x in probs]
tot = sum(scaled)
norm = [x/tot for x in scaled]

当然,您最好只使用bigfloat 或 numpy 并进行高精度数学运算。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-01-19
    • 1970-01-01
    • 2014-05-28
    • 2014-02-17
    • 2012-07-23
    • 1970-01-01
    • 2011-05-24
    相关资源
    最近更新 更多