Я пытаюсь создать дистрибутив, основанный на некоторых данных, которые я имею, а затем произвольно рисует из этого дистрибутива. Вот что у меня есть:
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, в print 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, в rvs 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. ру", строка 1212, в _ppf return 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 return 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, в brentq r = _zeros._brentq (f, a, b, xtol, maxiter, args, full_output, disp) ValueError: f (a) и f (b) должны иметь разные знаки
Edit
Для любопытных, следуя советам ниже, здесь код, который работает:
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 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)