Ich versuche, eine Verteilung basierend auf einigen Daten zu erstellen, die ich habe, und dann zufällig aus dieser Verteilung zu zeichnen. Hier ist, was ich habe:Erstellen neuer Distributionen in 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
Ich denke, das tut, was ich will, aber ich bekommen häufig einen Fehler (siehe unten), wenn ich versuche d.rvs()
zu tun, und d.rvs(100)
nie funktioniert. Mache ich etwas falsch? Gibt es einen leichteren oder besseren Weg dies zu tun? Wenn es ein Fehler in scipy ist, gibt es einen Weg, um es zu umgehen?
Schließlich gibt es weitere Dokumentation zum Erstellen von benutzerdefinierten Distributionen irgendwo? Das Beste, was ich gefunden habe, ist die Dokumentation scipy.stats.rv_continuous, die ziemlich spartanisch ist und keine nützlichen Beispiele enthält.
Die Zurückverfolgungs:
Traceback (most recent call last): File "testDistributions.py", line 19, in print d.rvs(size=100) File "/usr/local/lib/python2.6/dist-packages/scipy-0.10.0-py2.6-linux-x86_64.egg/scipy/stats/distributions.py", line 696, in rvs vals = self._rvs(*args) File "/usr/local/lib/python2.6/dist-packages/scipy-0.10.0-py2.6-linux-x86_64.egg/scipy/stats/distributions.py", line 1193, in _rvs Y = self._ppf(U,*args) File "/usr/local/lib/python2.6/dist-packages/scipy-0.10.0-py2.6-linux-x86_64.egg/scipy/stats/distributions.py", line 1212, in _ppf return self.vecfunc(q,*args) File "/usr/local/lib/python2.6/dist-packages/numpy-1.6.1-py2.6-linux-x86_64.egg/numpy/lib/function_base.py", line 1862, in call theout = self.thefunc(*newargs) File "/usr/local/lib/python2.6/dist-packages/scipy-0.10.0-py2.6-linux-x86_64.egg/scipy/stats/distributions.py", line 1158, in _ppf_single_call return optimize.brentq(self._ppf_to_solve, self.xa, self.xb, args=(q,)+args, xtol=self.xtol) File "/usr/local/lib/python2.6/dist-packages/scipy-0.10.0-py2.6-linux-x86_64.egg/scipy/optimize/zeros.py", line 366, in brentq r = _zeros._brentq(f,a,b,xtol,maxiter,args,full_output,disp) ValueError: f(a) and f(b) must have different signs
bearbeiten
Für diejenigen neugierig, im Anschluss an die Beratung in der Antwort unten, hier Code ist, das funktioniert:
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)
Also, wenn wir das oben genannte tun und 'randoms = getDistribution (Mydata)' und dann 'randoms = randoms.rvs (size = 1000) nennen' führt es die drei 'def' innerhalb der Klasse aus? d. h. Berechnung von PDF, Integration, etc? – ThePredator
Ich bekomme meine Randoms die Datenverteilung zu folgen, aber ich möchte es glätten, so dass es nicht genau der Datenverteilung folgt. Ich habe die Bandbreite im 'Kernel' manuell angepasst, um das zu tun. Zum Beispiel, wie wir eine PDF-Funktion angeben und dann die PDF-Funktion verwenden, um Randoms mit Metropolis Hastings zu erstellen. – ThePredator