Definir função de densidade de probabilidade personalizada em Python

20

Existe uma maneira de usar algum pacote Python estabelecido (por exemplo, SciPy) para definir minha própria função de densidade de probabilidade (sem dados anteriores, apenas ), para que eu possa fazer cálculos com ele (como obter a variância da variável aleatória contínua)? É claro que eu poderia, digamos, SymPy ou Sage, criar uma função simbólica e executar as operações, mas estou pensando se, em vez de fazer todo esse trabalho, posso usar um pacote já implementado.f(x)=umax+b

astrojuanlu
fonte
Obrigado por uma maneira fácil! Como você gera um histograma de números aleatórios implementando essa maneira de definir a função de distribuição personalizada?
Ankur Agrawal

Respostas:

23

Você tem que subclasse o rv_continuous classe em 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')

agora my_cv é uma variável aleatória contínua com o PDF fornecido e o intervalo [0,1]

Note-se que, neste exemplo, my_pdfe my_cvsão nomes arbitrários (que poderia ter sido qualquer coisa), mas _pdfé não arbitrária; e _cdfsão métodos em st.rv_continuousum dos quais deve ser substituído para que a subclasse funcione.

GertVdE
fonte
@GertVdE: O que "self" em def _pdf faz?
precisa
@Srivatsan: veja a resposta em Stack Overflow
GertVdE
Há um problema com a normalização, aqui: você precisa fornecer uma função de distribuição de probabilidade normalizada ( 3*x**2, aqui) ou a variável aleatória resultante produz resultados incorretos (você pode verificar my_cv.median(), por exemplo). Eu consertei o código.
Eric O Lebigot
@EOL Estou achando confuso o uso do termo "normalizado". o que é necessário, acredito, é que a função seja centrada em 0 e redimensionada para 1. mas essa resposta parece implicar que a normalização precisa estar acima do intervalo de x[0, 1]. você pode esclarecer?
dbliss
1
Talvez a maneira padrão seja usar my_cv.rvs()(o que pode levar um sizeargumento, para obter várias amostras de uma só vez). Acho que é isso da documentação ( docs.scipy.org/doc/scipy/reference/generated/… ).
Eric O Lebigot
15

Você deve verificar o sympy.stats. Ele fornece uma interface para lidar com variáveis ​​aleatórias. O exemplo a seguir fornece uma variável aleatória Xdefinida no intervalo da unidade com densidade2x

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)

Se você estiver interessado, essa abstração pode lidar com algumas manipulações bastante complexas.

MRocklin
fonte
Uau ... isso é incrível! Muito obrigado por esta contribuição. Eu vou manter um olho sobre este e seu blog
astrojuanlu