【问题标题】:SciPy: generating custom random variable from PMFSciPy:从 PMF 生成自定义随机变量
【发布时间】:2014-04-25 22:17:58
【问题描述】:

我正在尝试根据某个丑陋的分布在 Python 中生成随机变量。我有一个 PMF 的显式表达式,但它涉及一些产品,这使得获取和反转 CDF 变得不愉快(有关 PMF 的显式形式,请参见下面的代码)。

本质上,我试图通过其 PMF 在 Python 中定义一个随机变量,然后让内置代码完成从分布中采样的艰苦工作。如果 RV 的支持是有限的,我知道该怎么做,但这里的支持是可数无限的。

我目前尝试按照@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

基本上,np.arange() 列表似乎在 def _pmf() 函数中无法正常工作。我不知道为什么。谁能在这里启发我和/或指出解决方法?

编辑 1:通过 askewchan 解决了一些问题,编辑反映在上面。

编辑 2: askewchan 提出了一个使用阶乘函数的有趣近似值,但我正在寻找更精确的解决方案,例如我正在尝试使用 np.arange 的解决方案。

【问题讨论】:

  • 在“RV 只取有限多个值,但我的分布可以取任意大的正值”中的“取”是什么意思?您的意思是 pmf 的参数数量不定?还是说总体中的元素没有上限?
  • @askewchan:随机变量取任意大的值,pmf只有一个参数。换句话说,如果 X 是随机变量,那么对于任意大的 k,P(X=k) > 0。
  • 如果我理解正确,那么我认为这只是意味着b = inf 这实际上是rv_discrete 的默认行为。我假设你的 pmf 的积分是有限的(和 1)。
  • @askewchan:谢谢。我想我要问的是如何准确地将 pmf 提供给 rv_discrete 方法。如果我只有一个有限的值和概率列表,我知道如何做到这一点,但我不完全确定如何使其仅适用于任意函数。对不起,如果这太简单了......
  • 您收到该错误是因为pmf 必须能够接受k 的数组并返回p 的相同形状的数组。如果您需要帮助,我会编辑我的答案。

标签: python numpy scipy


【解决方案1】:

您应该能够像这样子类化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)

【讨论】:

  • 这绝对看起来应该有效。但是又出现了一个问题。我会将它添加到主体中,但无论如何我都赞成。谢谢。
  • 如果您发布 pmf I 或其他人的表格,也许可以测试可能的解决方案。
  • 嗯。我仍然收到关于“只有长度为 1 的数组......”的完全相同的错误,如果它对你来说运行正常,那么我可能只是做错了什么。我会考虑的。
  • 奇怪,这个错误几乎可以肯定来自np.arange,我没有在我的解决方案中使用它......你为alpha使用了什么值(我是否正确假设@987654332 @是你的单身param?)有时我会因为阶乘中的大值而出错,但对于长度为1的数组却没有。你确定那不是来自np.arange
  • scipy.special.gammaln代替factorial,最后用sum和exp,精度会高很多。
猜你喜欢
  • 1970-01-01
  • 2015-02-27
  • 2017-05-10
  • 2015-09-16
  • 2012-06-18
  • 2014-01-23
  • 1970-01-01
  • 1970-01-01
  • 2017-06-12
相关资源
最近更新 更多