Создайте один образец, следуя двум разным распределениям - PullRequest
1 голос
/ 24 марта 2020

Я хотел бы создать случайную выборку в интервале [0;1000] размером 1E4. Но следуют два разных распределения: одно в интервале [0;1], следующее за возрастающим экспоненциальным распределением, которое будет генерировать набор значений, близких к 1, относительно остальных, близких к 0. И затем, после генерации второй части моей выборки в интервале [1;1000] после распределения 1/r.

Я думаю, что более простой способ сделать это - разделить глобальную выборку на две разные выборки. Но я не знаю, как с этим справиться. Я пытался использовать какой-то дистрибутив библиотеки scipy, но я не нашел способа использовать их должным образом для генерации моей глобальной выборки. Что ты думаешь?

1 Ответ

2 голосов
/ 24 марта 2020

Вы можете использовать два отдельных распределения, но вам нужно убедиться, что количество выборок совпадает в граничной точке (r == 1). Таким образом, вам нужно оценить необходимое количество выборок для левого (exp) и правого (1 / r) распределения. Интегралы по двум распределениям дают следующее:

Это означает, что вероятность для левого распределения в r = 1 равна exp(1) / 1.7183, а для правого распределения - 1 / 6.9078. Так что это дает соотношение ratio = left / right = 10.928. Это означает, что вам нужно сгенерировать в ratio раз больше значений в правом интервале, чем в левом, чтобы в итоге получилось одинаковое количество выборок на границе. Допустим, вы хотите сгенерировать N выборок в общей сложности, это означает, что вам нужно сгенерировать N1 = N / (ratio + 1) выборок в левом (exp) интервале и N2 = N * ratio / (ratio + 1) выборок в правом (1 / r) интервале.

Вот пример кода:

import matplotlib.pyplot as plt
import numpy as np

r_max = 1000.0
integral_1 = np.exp(1.0) - 1.0  # 1.7183
integral_2 = np.log(r_max)      # 6.9078

N = 2_000_000  # total number of samples
ratio = np.exp(1.0) / integral_1 * integral_2  # 10.928
N1 = int(N / (ratio + 1))
N2 = int(N * ratio / (ratio + 1))

# Use inverse transform sampling in the following.
s1 = np.log(integral_1 * np.random.random(size=N1) + 1.0)
s2 = np.exp(integral_2 * np.random.random(size=N2))

samples = np.concatenate((s1, s2))
np.random.shuffle(samples)  # optionally shuffle the samples

plt.hist(samples, bins=int(20 * r_max))
plt.xlim([0, 5])
plt.show()

, который производит следующее распределение:

Example distribution

...