scipy 从自定义连续概率密度函数生成随机数

iecba09b  于 2022-11-10  发布在  其他
关注(0)|答案(1)|浏览(224)

正如标题所述,我正试图从一个自定义的连续概率密度函数中生成随机数,该函数为:

0.001257 *x^4 * e^(-0.285714 *x)

为此,我使用(在python 3上)scipy.stats.rv_continuous,然后使用rvs()来生成它们

from decimal import Decimal
from scipy import stats
import numpy as np

class my_distribution(stats.rv_continuous):
    def _pdf(self, x):
        return (Decimal(0.001257) *Decimal(x)**(4)*Decimal(np.exp(-0.285714 *x)))

distribution = my_distribution()
distribution.rvs()

请注意,我使用Decimal去掉了一个OverflowError: (34, 'Result too large')
但是,我仍然收到错误RuntimeError: Failed to converge after 100 iterations
这是怎么回事?什么是正确的方式来实现我需要做的事情?

sq1bmfud

sq1bmfud1#

我已经找到你的问题的原因了。
rvs默认使用数值积分,这是一个缓慢的过程,在某些情况下可能会失败。您的PDF可能就是其中之一,左边无限增长。
因此,应按如下方式指定分布的支持面(以下示例显示支持面位于区间[-4,4]中):

distribution = my_distribution(a = -4, b = 4)

在这个区间内,PDF将从上方被约束,允许积分(以及随机变量生成)正常工作。注意,默认情况下,rv_continuous假设分布在整个真实的线上都是支持的。
但是,这只适用于您在此给予的特定PDF,不一定适用于任意PDF。
通常,当你只给予rv_continuous子类一个PDF时,子类的rvsmean等将非常慢,因为每次生成随机变量或计算统计量时,该方法都需要对PDF进行积分。例如,随机变量的生成需要使用数值积分来对PDF进行积分。并且根据PDF的不同,该过程可能无法收敛。
在将来处理任意分布的情况下,尤其是速度非常重要的情况下,需要添加一个使用自己采样器的_rvs方法。一个例子是在相关问题的答案中给出的一个简单得多的拒绝采样器。
另请参见我的“从任意分布中采样”一节。

相关问题