正如标题所述,我正试图从一个自定义的连续概率密度函数中生成随机数,该函数为:
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
。
这是怎么回事?什么是正确的方式来实现我需要做的事情?
1条答案
按热度按时间sq1bmfud1#
我已经找到你的问题的原因了。
rvs
默认使用数值积分,这是一个缓慢的过程,在某些情况下可能会失败。您的PDF可能就是其中之一,左边无限增长。因此,应按如下方式指定分布的支持面(以下示例显示支持面位于区间[-4,4]中):
在这个区间内,PDF将从上方被约束,允许积分(以及随机变量生成)正常工作。注意,默认情况下,
rv_continuous
假设分布在整个真实的线上都是支持的。但是,这只适用于您在此给予的特定PDF,不一定适用于任意PDF。
通常,当你只给予
rv_continuous
子类一个PDF时,子类的rvs
、mean
等将非常慢,因为每次生成随机变量或计算统计量时,该方法都需要对PDF进行积分。例如,随机变量的生成需要使用数值积分来对PDF进行积分。并且根据PDF的不同,该过程可能无法收敛。在将来处理任意分布的情况下,尤其是速度非常重要的情况下,需要添加一个使用自己采样器的
_rvs
方法。一个例子是在相关问题的答案中给出的一个简单得多的拒绝采样器。另请参见我的“从任意分布中采样”一节。