【发布时间】:2012-05-27 13:23:12
【问题描述】:
我正在尝试根据我拥有的一些数据创建一个分布,然后从该分布中随机抽取。这是我所拥有的:
from scipy import stats
import numpy
def getDistribution(data):
kernel = stats.gaussian_kde(data)
class rv(stats.rv_continuous):
def _cdf(self, x):
return kernel.integrate_box_1d(-numpy.Inf, x)
return rv()
if __name__ == "__main__":
# pretend this is real data
data = numpy.concatenate((numpy.random.normal(2,5,100), numpy.random.normal(25,5,100)))
d = getDistribution(data)
print d.rvs(size=100) # this usually fails
我认为这是在做我想做的事,但是当我尝试执行 d.rvs() 时,我经常会遇到错误(见下文),而 d.rvs(100) 永远不会工作。难道我做错了什么?有没有更简单或更好的方法来做到这一点?如果它是 scipy 中的一个错误,有什么办法可以解决它吗?
最后,是否有更多关于在某处创建自定义发行版的文档?我发现的最好的是 scipy.stats.rv_continuous 文档,它非常简陋,没有包含有用的示例。
回溯:
Traceback(最近一次调用最后一次):文件“testDistributions.py”,行 19,在 打印 d.rvs(size=100) 文件“/usr/local/lib/python2.6/dist-packages/scipy-0.10.0-py2.6-linux-x86_64.egg/scipy/stats/distributions.py” , 第 696 行,在房车中 vals = self._rvs(*args) 文件“/usr/local/lib/python2.6/dist-packages/scipy-0.10.0-py2.6-linux-x86_64.egg/scipy/stats/distributions.py” , 第 1193 行,在 _rvs Y = self._ppf(U,*args) 文件“/usr/local/lib/python2.6/dist-packages/scipy-0.10.0-py2.6-linux-x86_64.egg/scipy/stats/distributions. py", 第 1212 行,在 _ppf 返回 self.vecfunc(q,*args) 文件“/usr/local/lib/python2.6/dist-packages/numpy-1.6.1-py2.6-linux-x86_64.egg/numpy/lib/function_base.py ", 第 1862 行,在 调用 theout = self.thefunc(*newargs) 文件“/usr/local/lib/python2.6/dist-packages/scipy-0.10.0-py2.6-linux-x86_64.egg/scipy/stats/distributions.py” , 第 1158 行,在 _ppf_single_call 返回 optimize.brentq(self._ppf_to_solve, self.xa, self.xb, args=(q,)+args, xtol=self.xtol) 文件 “/usr/local/lib/python2.6/dist-packages/scipy-0.10.0-py2.6-linux-x86_64.egg/scipy/optimize/zeros.py”, 第 366 行,在布伦特 r = _zeros._brentq(f,a,b,xtol,maxiter,args,full_output,disp) ValueError: f(a) and f(b) must have different sign
编辑
对于那些好奇的人,请按照以下答案中的建议,以下是有效的代码:
from scipy import stats
import numpy
def getDistribution(data):
kernel = stats.gaussian_kde(data)
class rv(stats.rv_continuous):
def _rvs(self, *x, **y):
# don't ask me why it's using self._size
# nor why I have to cast to int
return kernel.resample(int(self._size))
def _cdf(self, x):
return kernel.integrate_box_1d(-numpy.Inf, x)
def _pdf(self, x):
return kernel.evaluate(x)
return rv(name='kdedist', xa=-200, xb=200)
【问题讨论】:
-
那么当我们执行上述操作并调用
randoms = getDistribution(Mydata)然后调用randoms = randoms.rvs(size=1000)时,它会在类中执行三个def吗?即计算pdf,整合它等? -
我确实让我的随机数遵循数据分布,但我想对其进行平滑处理,使其不完全遵循数据分布。我一直在手动调整
kernel的带宽来做到这一点。例如,我们如何指定 PDF 函数,然后使用 PDF 函数使用 Metropolis Hastings 创建随机数。