You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Python的rv_discrete实现Polya-Aeppli分布?结果异常排查

Polya-Aeppli分布实现问题:代码错误与参数理解偏差

实现背景与代码

我尝试通过子类化scipy.stats.rv_discrete类、指定PMF(概率质量函数)的方式在Python中实现Polya-Aeppli(几何泊松)分布,代码如下:

from scipy.stats import rv_discrete
import numpy as np
import math

class PolyaAeppli(rv_discrete):

    def _pmf(self, k: np.ndarray, lambda_, theta_) -> np.ndarray:
        """
        Probability mass function for Polya-Aeppli distribution. Extension of Poisson distribution for
        modeling group arrivals.

        :param k: internal parameter of rv_discrete
        :param lambda_: arrival rate param of Poisson dist: [0, inf). The higher the lambda, the more arrivals
        :param theta_: probability param of Geometric dist: [0, 1]. The LOWER the theta, the more arrivals
        :return: probability values for each k
        """

        if isinstance(lambda_, np.ndarray or list):
            lambda_ = lambda_[0]. # 此处存在语法错误,多了一个英文句点
        if isinstance(theta_, np.ndarray or list):
            theta_ = theta_[0]
        k = np.asarray(k, dtype=int)
        res = np.zeros(len(k))
        for ix, k_ in enumerate(k):  # 暂未实现向量化
            if k_ == 0:
                res[ix] = np.exp(-lambda_)
            else:
                res[ix] = np.exp(-lambda_) * np.sum([(np.power(lambda_, i) / math.factorial(i)) *
                                                     ((1 - theta_) ** (k_ - i)) * (theta_ ** i) *
                                                     (comb(k_ - 1, i - 1)) for i in range(1, k_ + 1)])
        return res

问题现象

我用以下代码采样并绘制直方图,预期参数lambda_=0.9、theta_=0.9的d组平均到达数最大,但实际结果与预期不符:

PA = PolyaAeppli(name='polya_aeppli')

# 采样
resa = PA.rvs(lambda_=0.5, theta_=0.5, size=1000)
resb = PA.rvs(lambda_=0.5, theta_=0.9, size=1000)
resc = PA.rvs(lambda_=0.9, theta_=0.5, size=1000)
resd = PA.rvs(lambda_=0.9, theta_=0.9, size=1000)

# 绘制直方图
import matplotlib.pyplot as plt
plt.hist(resa, label='a', alpha=0.5)
plt.hist(resb, label='b', alpha=0.5)
plt.hist(resc, label='c', alpha=0.5)
plt.hist(resd, label='d', alpha=0.5)
plt.legend()
plt.show()

问题分析

1. 参数理解偏差

Polya-Aeppli分布本质是Poisson(λ)个独立几何分布变量的和,其中几何分布定义为「首次成功的次数」(取值为1,2,...),单变量期望为1/θ。因此Polya-Aeppli分布的整体期望公式为:
$$E[K] = \lambda \cdot \frac{1}{\theta}$$
按此公式计算各组期望:

  • a组:0.5 / 0.5 = 1
  • b组:0.5 / 0.9 ≈ 0.556
  • c组:0.9 / 0.5 = 1.8
  • d组:0.9 / 0.9 = 1

可见c组期望最大,d组与a组期望相同,这与你的预期完全相反。你代码中对theta的注释是正确的(theta越小,到达数越多),但实际预期时出现了逻辑偏差。

2. 代码中的错误

  • 语法错误:原代码中lambda_ = lambda_[0].多了一个英文句点,会导致运行报错。
  • 类型判断错误:isinstance(lambda_, np.ndarray or list)写法无效,应改为isinstance(lambda_, (np.ndarray, list)),否则只会判断是否为np.ndarray类型。
  • 缺失依赖:comb函数未导入,需添加from math import comb(Python3.10+支持)或from scipy.special import comb。

修正后的代码示例

from scipy.stats import rv_discrete
import numpy as np
import math
from math import comb

class PolyaAeppli(rv_discrete):

    def _pmf(self, k: np.ndarray, lambda_, theta_) -> np.ndarray:
        """
        Probability mass function for Polya-Aeppli distribution. Extension of Poisson distribution for
        modeling group arrivals.

        :param k: internal parameter of rv_discrete
        :param lambda_: arrival rate param of Poisson dist: [0, inf). The higher the lambda, the more arrivals
        :param theta_: probability param of Geometric dist: [0, 1]. The LOWER the theta, the more arrivals
        :return: probability values for each k
        """

        # 修正类型判断逻辑
        if isinstance(lambda_, (np.ndarray, list)):
            lambda_ = lambda_[0]
        if isinstance(theta_, (np.ndarray, list)):
            theta_ = theta_[0]
        k = np.asarray(k, dtype=int)
        res = np.zeros(len(k))
        
        for ix, k_ in enumerate(k):
            if k_ == 0:
                res[ix] = math.exp(-lambda_)
            else:
                sum_term = 0.0
                for i in range(1, k_ + 1):
                    poisson_term = math.pow(lambda_, i) / math.factorial(i)
                    neg_binom_term = comb(k_ - 1, i - 1) * (theta_ ** i) * ((1 - theta_) ** (k_ - i))
                    sum_term += poisson_term * neg_binom_term
                res[ix] = math.exp(-lambda_) * sum_term
        return res

内容的提问来源于stack exchange,提问作者Nathan Vaartjes

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 13:37:01