Définir une fonction de densité de probabilité personnalisée en Python

20

Existe-t-il un moyen, en utilisant un package Python établi (par exemple SciPy), de définir ma propre fonction de densité de probabilité (sans aucune donnée préalable, juste ), afin que je puisse ensuite faire des calculs avec elle (comme obtenir la variance de la variable aléatoire continue)? Bien sûr, je pourrais prendre, disons, SymPy ou Sage, créer une fonction symbolique et faire les opérations, mais je me demande si au lieu de faire tout ce travail moi-même, je peux utiliser un package déjà implémenté.F(X)=uneX+b

astrojuanlu
la source
Merci pour un moyen simple! Comment générer un histogramme de nombres aléatoires mettant en œuvre cette façon de définir la fonction de distribution personnalisée?
Ankur Agrawal

Réponses:

23

Vous devez sous- classer la classe rv_continuous dans 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')

maintenant mon_cv est une variable aléatoire continue avec le PDF donné et la plage [0,1]

Notez que dans cet exemple my_pdfet my_cvsont des noms arbitraires (qui auraient pu être n'importe quoi), mais ne_pdf sont pas arbitraires; et _cdfsont des méthodes st.rv_continuousdont l'une doit être écrasée pour que le sous-classement fonctionne.

GertVdE
la source
@GertVdE: Que fait "self" dans def _pdf?
Srivatsan
@Srivatsan: voir la réponse sur Stack Overflow
GertVdE
Il y a un problème avec la normalisation, ici: vous devez donner une fonction de distribution de probabilité normalisée ( 3*x**2, ici), ou la variable aléatoire résultante donne des résultats incorrects (vous pouvez vérifier my_cv.median(), par exemple). J'ai corrigé le code.
Eric O Lebigot
@EOL je trouve votre utilisation du terme "normalisé" déroutant. ce qui est nécessaire, je crois, est que la fonction soit centrée à 0 et mise à l'échelle à 1. mais cette réponse semble impliquer que la normalisation doit être dans la plage de x[0, 1]. Pouvez-vous clarifier?
dbliss
1
La méthode standard est peut-être d'utiliser my_cv.rvs()(qui peut prendre un sizeargument, pour obtenir plusieurs échantillons en une seule fois). C'est ce que je suppose de la documentation ( docs.scipy.org/doc/scipy/reference/generated/… ).
Eric O Lebigot
15

Vous devriez vérifier sympy.stats. Il fournit une interface pour gérer les variables aléatoires. L'exemple suivant fournit une variable aléatoire Xdéfinie sur l'intervalle unitaire avec la densité2x

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)

Si vous êtes intéressé, cette abstraction peut gérer des manipulations assez complexes.

MRocklin
la source
Wow ... c'est tout simplement génial! Merci beaucoup pour cette contribution. Je garderai un œil sur cela et votre blog
astrojuanlu