Definieren Sie eine benutzerdefinierte Wahrscheinlichkeitsdichtefunktion in Python

20

Gibt es eine Möglichkeit, mithilfe eines etablierten Python-Pakets (z. B. SciPy) meine eigene Wahrscheinlichkeitsdichtefunktion zu definieren (ohne vorherige Daten, nur ), damit ich dann Berechnungen damit durchführen kann (z. B. die Varianz der stetigen Zufallsvariablen erhalten)? Natürlich könnte ich zum Beispiel SymPy oder Sage nehmen, eine symbolische Funktion erstellen und die Operationen ausführen, aber ich frage mich, ob ich statt all dieser Arbeit ein bereits implementiertes Paket verwenden kann.f(x)=ax+b

Astrojuanlu
quelle
Vielen Dank für einen einfachen Weg! Wie generieren Sie ein Histogramm von Zufallszahlen, indem Sie diese Art der Definition der benutzerdefinierten Verteilungsfunktion implementieren?
Ankur Agrawal

Antworten:

23

Sie haben die Unterklasse rv_continuous Klasse in scipy.stats

import scipy.stats as st

class my_pdf(st.rv_continuous):
    def _pdf(self,x):
        return 3*x**2  # Normalized over its range, in this case [0,1]

my_cv = my_pdf(a=0, b=1, name='my_pdf')

jetzt ist my_cv eine kontinuierliche Zufallsvariable mit dem angegebenen PDF und Bereich [0,1]

Beachten Sie, dass in diesem Beispiel my_pdfund my_cvsind beliebige Namen (das alles gewesen sein könnte), aber _pdfist nicht willkürlich; es und _cdfsind Methoden inst.rv_continuous von denen eine überschrieben werden muss, damit die Unterklasse funktioniert.

GertVdE
quelle
@GertVdE: Was macht "self" in def_pdf?
Srivatsan
@Srivatsan: Siehe die Antwort auf Stack Overflow
GertVdE
Es gibt ein Problem mit der Normalisierung, hier: Sie müssen eine normalisierte Wahrscheinlichkeitsverteilungsfunktion angeben ( 3*x**2hier), oder die resultierende Zufallsvariable liefert falsche Ergebnisse (Sie können my_cv.median()zum Beispiel überprüfen ). Ich habe den Code korrigiert.
Eric O Lebigot
@EOL Ich finde Ihre Verwendung des Begriffs "normalisiert" verwirrend. Ich glaube, man muss die Funktion auf 0 zentrieren und auf 1 skalieren, aber diese Antwort scheint zu implizieren, dass die Normalisierung über dem Bereich von x[0, 1] liegen muss. könntest Du das erläutern?
Dbliss
1
Möglicherweise ist die Standardmethode die Verwendung my_cv.rvs()(was ein sizeArgument sein kann, um mehrere Proben auf einmal zu erhalten). Dies ist, was ich aus der Dokumentation ( docs.scipy.org/doc/scipy/reference/generated/… ) schätze .
Eric O Lebigot
15

Sie sollten sympy.stats auschecken. Es bietet eine Schnittstelle zum Umgang mit Zufallsvariablen. Das folgende Beispiel enthält eine Zufallsvariable, Xdie für das Einheitsintervall mit Dichte definiert ist2x

In [1]: from sympy.stats import *
In [2]: x = Symbol('x')
In [3]: X = ContinuousRV(x, 2*x, Interval(0, 1))

In [4]: P(X>.5) 
Out[4]: 0.750000000000000

In [5]: Var(X) # variance
Out[5]: 1/18

In [6]: E(2*cos(X)+X**2) # complex expressions are ok too
Out[6]: -7/2 + 4cos(1) + 4sin(1)

Wenn Sie interessiert sind, kann diese Abstraktion einige ziemlich komplexe Manipulationen verarbeiten.

MRocklin
quelle
Wow ... das ist einfach geil! Vielen Dank für diesen Beitrag. Ich werde dies und Ihr Blog im Auge behalten
astrojuanlu