poisson_binom.sf 返回 0,极小上尾概率怎样核对
SciPy 1.18.1 的 Poisson 二项分布上尾可能受 1-cdf 消减影响。说明包含端点的 sf 写法、可表示尾部的 PMF 求和与更小概率的边界。
poisson_binom.sf() 返回 0,logsf() 是 -inf,但输入的伯努利概率都大于零,理论上对应事件仍可能发生。也可能出现相反情况:真正的上尾远小于双精度范围,接口却返回约 1e-16 的非零值。极端尾部不能只看结果是否位于 0 到 1 之间。
SciPy 1.18.1 的 poisson_binom 没有独立的上尾实现,沿用 1-cdf,随后取对数。CDF 已非常接近 1 时,相减会丢掉尾部信息;再调用 logsf 不能把丢失的位数补回来。相关路径在 2026 年 10 月开发版本也有记录,不能假设换成开发包即可解决。
先分清 sf 的端点
设 S 是独立但成功概率可各不相同的伯努利变量之和。sf(t) 表达 P(S>t);要求 P(S>=k) 时,应调用 sf(k-1)。先核对这一个差值,避免把数值精度问题与事件定义错位混在一起。
还要保留概率向量 p 的实际浮点值、形状与 dtype。输入的小数已经舍入后,高精度对照应明确采用这些浮点值,还是原始十进制参数;两者不是完全同一问题。
尾部仍可表示时,直接累加概率质量
对规模可控、概率向量是一维且 0<=k<=len(p) 的任务,可以把尾部的 PMF 相加,避开从 1 中相减:
import numpy as np
from scipy.stats import poisson_binom
p = np.array([(1 + i % 9) / 128 for i in range(32)])
k = 24
terms = poisson_binom.pmf(np.arange(k, p.size + 1), p)
tail = terms.sum(dtype=np.float64)
这组输入的上尾约为 1.19635e-29,处于 float64 可表示范围。示例是对应有限尾和的计算方式,不承诺所有规模和所有概率组合都达到相同精度。批量参数还有广播维度,不能不看形状就照抄一维求和轴。
调用前先验证概率合法、k 为整数,并按业务处理 k<=0 与 k>len(p) 的边界。大规模尾和可能成本很高,应在原计算预算内评估。
下溢后的 log 仍然无能为力
若真实概率约为 1e-516,普通 float64 的概率值会下溢。先求和得到零,再取 log,仍只能得到 -inf;把这个零转成更宽类型也不会恢复信息。需要有限对数概率的任务,应采用经过核对的对数域或任意精度算法,并给出精度与资源预算。
把成功改成失败计数,有时可把上尾换成下尾,但当 p 极小时,1-p 可能直接舍入为 1,转换本身已丢失信息。也不能把所有不同的 p 替换成均值后套普通二项分布,那是在更换分布。
验收将可表示的小尾部、超出普通浮点范围的尾部,以及普通概率分别比较,使用有明确精度依据的参考计算。仅检查 sf+cdf≈1 会漏掉本题:极小上尾被误写为零时,这个等式依然可能成立。保留原输入和已输出结果,受影响的显著性判断或排序应按任务重算,不能把零统一替换成一个经验下限。


