Numpy случайная выборка из нескольких распределений - PullRequest
0 голосов
/ 26 февраля 2020

Каков эффективный способ выборки N чисел, где каждое число является выборкой, сначала выбирая случайное распределение из фиксированного заранее определенного списка (используя некоторый определенный c дискретный распределение), а затем выбирая из этого выбранного распределения.

Так, например, если мы хотим выбрать 0 с вероятностью 0,30, 1 с вероятностью 0,30 и с вероятностью 0,40, мы хотим выбрать любое действительное число в [0,1) с равномерным распределением, мы можем написать:

np.choose(
    np.random.choice(2, size=N, p=[0.6, 0.4]),
    np.vstack((
        np.random.choice(2, size=(1,N)),
        np.random.uniform(size=(1,N))
    )))

Однако при этом генерируется N x D случайных чисел (где D - количество распределений) и используется пространство N x D. Существует ли более эффективный векторизованный (т.е. нет O(N) python for-loop) способ достижения этого?

Если не в общем случае, может ли указанное выше объединенное распределение c быть как-то эффективно сгенерировано иначе?

1 Ответ

0 голосов
/ 26 февраля 2020

Вы можете использовать np.unique, чтобы точно определить, сколько образцов вам нужно из каждого распределения. Для этого требуется Python l oop размера O(D). Пространственная сложность составляет O(N), но временная сложность все еще O(N * D). Вы можете сбросить его до O(N), рассчитав разреженный индекс для каждого D.

N = 10
D = 2

distributions = [
  lambda n: np.random.choice(2, size=n),
  lambda n: np.random.uniform(n),
]

ds = np.random.choice(D, p=[0.6, 0.4], size=N)
uniques, inverse, counts = np.unique(ds, return_inverse=True, return_counts=True)
result = np.zeros(N)
for d, c in zip(uniques, counts):
  result[inverse==d] = distributions[d](c)
...