Definir la función de densidad de probabilidad personalizada en Python

20

¿Hay alguna manera de usar algún paquete Python establecido (por ejemplo, SciPy) para definir mi propia función de densidad de probabilidad (sin datos previos, solo ), para que luego pueda hacer cálculos con ella (como obtener la varianza de la variable aleatoria continua) Por supuesto, podría tomar, por ejemplo, SymPy o Sage, crear una función simbólica y hacer las operaciones, pero me pregunto si en lugar de hacer todo este trabajo yo mismo puedo hacer uso de un paquete ya implementado.F(X)=unX+si

astrojuanlu
fuente
Gracias por una manera fácil! ¿Cómo se genera un histograma de números aleatorios implementando esta forma de definir la función de distribución personalizada?
Ankur Agrawal

Respuestas:

23

Debe subclasificar la clase rv_continuous en 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')

ahora my_cv es una variable aleatoria continua con el PDF y rango dados [0,1]

Tenga en cuenta que en este ejemplo my_pdfy my_cvson nombres arbitrarios (que podrían haber sido cualquier cosa), pero no_pdf es arbitrario; y son métodos en uno de los cuales deben sobrescribirse para que la subclase funcione._cdfst.rv_continuous

GertVdE
fuente
@GertVdE: ¿Qué hace "self" en def _pdf do ??
Srivatsan
@Srivatsan: vea la respuesta en Stack Overflow
GertVdE
Aquí hay un problema con la normalización: debe proporcionar una función de distribución de probabilidad normalizada ( 3*x**2, aquí), o la variable aleatoria resultante produce resultados incorrectos (puede verificar my_cv.median(), por ejemplo). Arreglé el código.
Eric O Lebigot
@EOL Estoy confundiendo tu uso del término "normalizado". lo que se necesita, creo, es que la función esté centrada en 0 y escalada a 1. pero esta respuesta parece implicar que la normalización debe estar por encima del rango de x[0, 1]. puedes aclarar?
dbliss
1
Quizás la forma estándar es usar my_cv.rvs()(que puede tomar un sizeargumento, para obtener múltiples muestras de una vez). Esto es lo que supongo de la documentación ( docs.scipy.org/doc/scipy/reference/generated/… ).
Eric O Lebigot
15

Deberías consultar sympy.stats. Proporciona una interfaz para manejar variables aleatorias. El siguiente ejemplo proporciona una variable aleatoria Xdefinida en el intervalo unitario con densidad2x

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 está interesado, esta abstracción puede manejar algunas manipulaciones bastante complejas.

MRocklin
fuente
Wow ... esto es simplemente increíble! Muchas gracias por este aporte. Voy a mantener un ojo en esto y tu blog
astrojuanlu