Определить пользовательскую функцию плотности вероятности в Python

20

Есть ли способ, используя какой-то установленный пакет Python (например, SciPy), чтобы определить мою собственную функцию плотности вероятности (без каких-либо предварительных данных, просто ), чтобы я мог затем сделать вычисления с ней (например, получение дисперсии непрерывной случайной величины)? Конечно, я мог бы взять, скажем, SymPy или Sage, создать символическую функцию и выполнить операции, но мне интересно, могу ли я вместо того, чтобы делать всю эту работу сам, использовать уже реализованный пакет.е(Икс)знак равноaИкс+б

astrojuanlu
источник
Спасибо за простой способ! Как вы генерируете гистограмму случайных чисел, реализуя этот способ определения пользовательской функции распределения?
Анкур Агравал

Ответы:

23

Вы должны создать подкласс класса rv_continuous в 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')

теперь my_cv - непрерывная случайная величина с заданным PDF и диапазоном [0,1]

Обратите внимание , что в этом примере my_pdfи my_cvпроизвольные имена (которые могли бы что - нибудь), но _pdfэто не произвольно; это и _cdfесть методы, st.rv_continuousодин из которых должен быть перезаписан, чтобы подкласс работал.

GertVdE
источник
@GertVdE: Что делает "self" в def _pdf ??
Шриватсан
Здесь есть проблема с нормализацией: вам нужно дать нормализованную функцию распределения вероятностей ( 3*x**2здесь), или результирующая случайная переменная дает неверные результаты (вы можете проверить my_cv.median(), например). Я исправил код.
Эрик О Лебиго
@EOL Я нахожу, что использование термина "нормализовано" сбивает с толку. Мне кажется, что необходимо, чтобы функция была центрирована в 0 и масштабирована до 1. Но этот ответ, по-видимому, подразумевает, что нормализация должна быть в диапазоне x[0, 1]. можешь уточнить?
dbliss
1
Возможно, стандартным способом является использование my_cv.rvs()(которое может принимать sizeаргумент для получения нескольких выборок за один раз). Это то, что я предполагаю из документации ( docs.scipy.org/doc/scipy/reference/generated/… ).
Эрик О Лебиго
15

Вы должны проверить sympy.stats. Он предоставляет интерфейс для работы со случайными переменными. В следующем примере представлена ​​случайная величина, Xопределенная на единичном интервале с плотностью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)

Если вам интересно, эта абстракция может обрабатывать довольно сложные манипуляции.

MRocklin
источник
Вау ... это просто потрясающе! Большое спасибо за этот вклад. Я буду следить за этим и вашим блогом
astrojuanlu