Создание новых дистрибутивов в scipy

Я пытаюсь создать дистрибутив на основе некоторых данных, которые у меня есть, а затем случайным образом извлечь из этого дистрибутива. Вот что у меня есть:

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, которая довольно спартанская и не содержит полезных примеров.

Трассировка:

Трассировка (последний последний вызов): Файл "testDistributions.py", строка 19, в распечатать файл d.rvs (размер = 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. ру", строка 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.ру", строка 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 optimise.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) должны иметь разные знаки

Изменить

Для тех, кому любопытно, после совет в ответе ниже, вот код, который работает:

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)
11
задан Noah 21 May 2012 в 20:06
поделиться