SciPy:从PMF生成自定义随机变量

5 投票
1 回答
2546 浏览
提问于 2025-04-18 04:07

我正在尝试在Python中生成一些随机变量,这些变量遵循一种比较复杂的分布。我有一个明确的概率质量函数(PMF)的表达式,但里面有一些乘法运算,这让求出和反转累积分布函数(CDF)变得很麻烦(下面的代码展示了PMF的具体形式)。

简单来说,我想在Python中通过PMF来定义一个随机变量,然后让内置的代码来处理从这个分布中抽样的工作。如果随机变量的取值是有限的,我知道怎么做,但在这里,取值是可数无限的。

我目前根据@askewchan的建议尝试运行的代码是:

import scipy as sp
import numpy as np

class x_gen(sp.stats.rv_discrete):
    def _pmf(self,k,param):
        num = np.arange(1+param, k+param, 1)
        denom = np.arange(3+2*param, k+3+2*param, 1)

        p = (2+param)*(np.prod(num)/np.prod(denom))

        return p

pa_limit = limitrv_gen()
print pa_limit.rvs(alpha,n=1)

然而,运行时出现了错误:

File "limiting_sim.py", line 42, in _pmf
    num = np.arange(1+param, k+param, 1)
TypeError: only length-1 arrays can be converted to Python scalars

基本上,看起来在def _pmf()函数内部,np.arange()这个列表似乎没有正常工作。我不知道为什么会这样。有没有人能帮我解答一下,或者指出一个解决办法?

编辑 1:根据askewchan的提问,澄清了一些问题,以上的编辑已反映出来。

编辑 2:askewchan建议使用阶乘函数进行一种有趣的近似,但我更想要一个精确的解决方案,比如我正在尝试用np.arange实现的那种。

1 个回答

4

你可以像下面这样来扩展 rv_discrete 类:

class mydist_gen(rv_discrete):
    def _pmf(self, n, param):
        return yourpmf(n, param)

然后你可以用下面的方式创建一个分布实例:

mydist = mydist_gen()

接着可以用下面的方式生成样本:

mydist.rvs(param, size=1000)

或者你也可以创建一个固定的分布对象,方法是:

mydistp = mydist(param)

最后可以用下面的方式生成样本:

mydistp.rvs(1000)

根据你的例子,这样应该是可以工作的,因为 factorial 会自动处理不同的输入。但如果 alpha 的值足够大,可能会出现问题:

import scipy as sp
import numpy as np
from scipy.misc import factorial

class limitrv_gen(sp.stats.rv_discrete):
    def _pmf(self, k, alpha):
        #num = np.prod(np.arange(1+alpha, k+alpha))
        num = factorial(k+alpha-1) / factorial(alpha)
        #denom = np.prod(np.arange(3+2*alpha, k+3+2*alpha))
        denom = factorial(k + 2 + 2*alpha) / factorial(2 + 2*alpha)

        return (2+alpha) * num / denom

pa_limit = limitrv_gen()
alpha = 100
pa_limit.rvs(alpha, size=10)

撰写回答