Учитывая дискретное распределение, как мне округлить число до ближайшего значения в этом распределении? - PullRequest
1 голос
/ 23 марта 2020

В конечном итоге я хочу округлить ожидаемое значение распределения дискретной случайной величины до действительного числа в распределении. Например, если я рисую равномерно из чисел [1, 5, 6], ожидаемое значение равно 4, но я хочу вернуть ему самое близкое число (ie, 5).

from scipy.stats import *
xk = (1, 5, 6)
pk = np.ones(len(xk))/len(xk)
custom = rv_discrete(name='custom', values=(xk, pk))
print(custom.expect())   
# 4.0

def round_discrete(discrete_rv_dist, val):
    # do something here
    return answer

print(round_discrete(custom, custom.expect()))
# 5.0

Я не знаю, априори, какое распределение будет использоваться (ie может не быть целым числом, может быть неограниченным распределением), поэтому я действительно изо всех сил пытаюсь придумать алгоритм, который достаточно универсален c. Редактировать: я только что узнал, что rv_discrete не работает с нецелыми значениями xk.

Что касается почему Я хочу сделать это, я собираю симуляцию Монте-Карло, и хотите «номинальное» значение для каждого распределения. Я думаю, что EV является физически более подходящим, чем режим или медиана. У меня могут быть значения в последующем моделировании, которые должны быть одним из нескольких дискретных вариантов, поэтому передача значения, не входящего в этот набор, недопустима.

Если уже есть хороший способ сделать это в Python это было бы здорово, иначе я могу интерпретировать математику в код.

Ответы [ 3 ]

1 голос
/ 23 марта 2020

Разобрался, и проверил, как работает. Если я вставлю свое значение X в файл cdf, то я смогу включить эту вероятность P = cdf (X) в файл ppf. Значения в ppf (P + - epsilon) дадут мне самые близкие значения в наборе X.

Или, что более геометрически, для дискретного pmf точка (X, P) будет l ie на горизонтальная часть соответствующего cdf. Когда вы инвертируете cdf, (P, X) теперь находится в вертикальном сечении ppf. Взяв P + - eps, вы получите 2 ближайших плоских участка ppf, связанных с этим вертикальным скачком, которые соответствуют действительным значениям X1, X2. Затем вы можете сделать простую разницу, чтобы выяснить, что ближе к вашему целевому значению.

import numpy as np
eps = np.finfo(float).eps

ev = custom.expect()
p = custom.cdf(ev)
ev_candidates = custom.ppf([p - eps, p, p + eps])
ev_candidates_distance = abs(ev_candidates - ev)
ev_closest = ev_candidates[np.argmin(ev_candidates_distance)]
print(ev_closest)
# 5.0

Термины:
pmf - функция вероятности массы
cdf - накопительная функция распределения (накопленная сумма pdf)
ppf - функция процентного пункта (обратная к cdf)
eps - epsilon (наименьшее возможное приращение)

1 голос
/ 23 марта 2020

Вот код R, который, я думаю, будет делать то, что вы хотите, используя данные Пуассона для иллюстрации:

set.seed(322)
x = rpois(100, 7)      # 100 obs from POIS(7)
a = mean(x); a
[1] 7.16               # so 7 is the value we want
d = min(abs(x-a)); d   # min distance btw a and actual Pois val
[1] 0.16
u = unique(x); u       # unique Pois values observed
[1]  7  5  4 10  2  9  8  6 11  3 13 14 12 15
v = u[abs(u-a)==d]; v  # unique val closest to a
[1] 7

Надеюсь, вы сможете перевести его на Python.

Еще один прогон:

set.seed(323)
x = rpois(100, 20)
a = mean(x); a
[1] 20.32
d = min(abs(x-a)); d
[1] 0.32
u = unique(x)
v = u[abs(u-a)==d]; v
[1] 20

x
 [1] 17 16 20 23 23 20 19 23 21 19 21 20 22 25 13 15 19 19 14 27 19 30 17 19 23
[26] 16 23 26 33 16 11 23 14 21 24 12 18 20 20 19 26 12 22 24 20 22 17 23 11 19
[51] 19 26 17 17 11 17 23 21 26 13 18 28 22 14 17 25 28 24 16 15 25 26 22 15 23
[76] 27 19 21 17 23 21 24 23 22 23 18 25 14 24 25 19 19 21 22 16 28 18 11 25 23
u
 [1] 17 16 20 23 19 21 22 25 13 15 14 27 30 26 33 11 24 12 18 28
0 голосов
/ 23 марта 2020

Поможет ли функция ceil из математической библиотеки? Например:

from math import ceil
print(float(ceil(3.333333333333333)))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...