我想使用scipy在0.15到10.1范围内从自定义函数中随机抽样。但是,我的样本高度偏向0.15的左边界。实际上,所有50000个采样点都小于0.16。我不确定我的代码有什么问题。
import numpy as np
from scipy import stats
class your_distribution(stats.rv_continuous):
def _pdf(self, x):
p0 = 10.9949;
p1 = 0.394447;
p2 = 12818.4;
p3 = 2.38898;
return ((p1*p3)/(p3*p0+p2*p1))*(p0*np.exp(-1.0*p1*x))+(p2*np.exp(-1.0*p3*x))
distribution = your_distribution(a=0.15, b=10.1)
sample = distribution.rvs(size=50000)
答案 0 :(得分:1)
您实施为_pdf()
的功能不是PDF。要成为PDF,[a,b]上的积分必须为1. PDF的积分不是1,大约是3750:
In [27]: from scipy.integrate import quad
In [28]: quad(distribution.pdf, distribution.a, distribution.b)
Out[28]: (3749.6759222061523, 6.886284755966421e-09)
如果作为快速黑客,我按如下方式修改您的发行版:
class your_distribution(stats.rv_continuous):
def _pdf(self, x):
p0 = 10.9949;
p1 = 0.394447;
p2 = 12818.4;
p3 = 2.38898;
p = ((p1*p3)/(p3*p0+p2*p1))*(p0*np.exp(-1.0*p1*x))+(p2*np.exp(-1.0*p3*x))
return p / 3749.6759222061523
然后按预期工作。
(这是一个快速的黑客攻击,因为规范化常数通常应取决于a
和b
。)
答案 1 :(得分:0)
您的代码没有问题。问题可能在于您的发行版的定义。随着x
变小,这渐渐变大。因此,由于您将分布支持的下限指定为a=0.15
,因此该值将对应于渐近概率1
。
请注意,支持的下限不是x
的下限
如果你绘制pdf
,你可以检查它是否从x = -292
附近的点接收到它的所有质量。通过指定a=0.15
生效,您可以将概率峰值移至0.15
我怀疑你想要实现的是x<0.15
概率为零的分布。这可以通过修改自定义分布来实现,如下所示
class your_distribution(stats.rv_continuous):
def _pdf(self, x):
p0 = 10.9949;
p1 = 0.394447;
p2 = 12818.4;
p3 = 2.38898;
if x < 0.15:
return 0
return ((p1*p3)/(p3*p0+p2*p1))*(p0*np.exp(-1.0*p1*x))+(p2*np.exp(-1.0*p3*x))
答案 2 :(得分:0)
我解决了问题(在朋友的帮助下)!
事实证明我的pdf没有正确规范化,因为我错过了一个括号。正确的pdf是((p1*p3)/(p3*p0+p2*p1))*((p0*np.exp(-1.0*p1*x))+(p2*np.exp(-1.0*p3*x)))
。