У меня есть файл с некоторыми вероятностями для разных значений, например:
1 0.1
2 0.05
3 0.05
4 0.2
5 0.4
6 0.2
Я хотел бы генерировать случайные числа, используя это распределение. Существует ли существующий модуль, который этим занимается? Довольно просто написать код самостоятельно (построить кумулятивную функцию плотности, сгенерировать случайное значение [0,1] и выбрать соответствующее значение), но похоже, что это должна быть общая проблема, и, возможно, кто-то создал функцию / модуль для Это.
Мне это нужно, потому что я хочу сгенерировать список дней рождения (который не соответствует никакому распределению в стандартном random
модуле).
random.choice()
? Вы составляете главный список с нужным количеством вхождений и выбираете одно. Это, конечно, повторяющийся вопрос.Ответы:
scipy.stats.rv_discrete
может быть то, что вы хотите. Вы можете указать свои вероятности с помощьюvalues
параметра. Затем вы можете использоватьrvs()
метод объекта распределения для генерации случайных чисел.Как отметил Евгений Пахомов в комментариях, вы также можете передать
p
параметр ключевого словаnumpy.random.choice()
, напримерЕсли вы используете Python 3.6 или выше, вы можете использовать
random.choices()
стандартную библиотеку - см. Ответ Марка Дикинсона .источник
numpy.random.choice()
почти в 20 раз быстрее.numpy.random.choice(numpy.arange(1, 7), p=[0.1, 0.05, 0.05, 0.2, 0.4, 0.2])
Начиная с Python 3.6, в стандартной библиотеке Python есть решение, а именно
random.choices
.Пример использования: давайте настроим совокупность и веса, соответствующие значениям в вопросе OP:
Теперь
choices(population, weights)
генерирует один образец:Необязательный аргумент, содержащий только ключевое слово,
k
позволяет запросить более одного образца одновременно. Это ценно, потому что есть некоторая подготовительная работа,random.choices
которую нужно проделывать каждый раз, когда он вызывается, перед генерацией любых семплов; Создавая множество образцов одновременно, нам нужно сделать эту подготовительную работу только один раз. Здесь мы генерируем миллион выборок и используем ихcollections.Counter
для проверки того, что полученное нами распределение примерно соответствует заданным нами весам.источник
Преимущество создания списка с использованием CDF состоит в том, что вы можете использовать двоичный поиск. Хотя вам нужно O (n) времени и места для предварительной обработки, вы можете получить k чисел за O (k log n). Поскольку обычные списки Python неэффективны, вы можете использовать
array
module.Если вы настаиваете на постоянном пространстве, вы можете сделать следующее; O (n) время, O (1) пространство.
источник
l[-1]
возвращает последний элемент списка?Может, уже поздно. Но вы можете использовать
numpy.random.choice()
, передавp
параметр:источник
random.choice()
- см. Комментарии.numpy.random.choice()
полностью отличается отrandom.choice()
распределения вероятностей и поддерживает его.(Хорошо, я знаю, что вы просите термоусадочную пленку, но, возможно, эти самодельные решения были недостаточно лаконичными, на ваш вкус. :-)
Я псевдо-подтвердил, что это работает, глядя на вывод этого выражения:
источник
i
не является объектом.Я написал решение для рисования случайных выборок из пользовательского непрерывного распределения .
Мне это нужно для аналогичного варианта использования (например, для генерации случайных дат с заданным распределением вероятностей).
Вам просто нужны функции
random_custDist
и линияsamples=random_custDist(x0,x1,custDist=custDist,size=1000)
. Остальное украшение ^^.Производительность этого решения, конечно, можно улучшить, но я предпочитаю удобочитаемость.
источник
Составьте список предметов на основе их
weights
:Оптимизация может заключаться в нормализации сумм по наибольшему общему делителю для уменьшения целевого списка.
Также это может быть интересно.
источник
Другой ответ, наверное, быстрее :)
источник
Проверка:
источник
на основе других решений вы генерируете накопительное распределение (как целое число или с плавающей запятой, как хотите), затем вы можете использовать пополам, чтобы сделать это быстро
это простой пример (здесь я использовал целые числа)
get_cdf
функция будет преобразовать его с 20, 60, 10, 10 в 20, 20 + 60, 20 + 60 + 10, 20 + 60 + 10 + 10теперь мы выбираем случайное число до 20 + 60 + 10 + 10, используя
random.randint
затем мы используем биссектрису, чтобы быстро получить фактическое значениеисточник
вы можете взглянуть на распределения выборки NumPy Random
источник
Ни один из этих ответов не является особенно ясным или простым.
Вот простой и понятный метод, который гарантированно работает.
Накопление_нормальностей_процессоров принимает словарь,
p
который отображает символы на вероятности ИЛИ частоты. Он выводит полезный список кортежей, из которых нужно делать выбор.Урожайность:
Почему это работает
На этапе накопления каждый символ превращается в интервал между ним и вероятностью или частотой предыдущих символов (или 0 в случае первого символа). Эти интервалы можно использовать для выбора (и, таким образом, выборки предоставленного распределения), просто переходя по списку, пока случайное число в интервале 0,0 -> 1,0 (подготовленное ранее) не станет меньше или равно конечной точке интервала текущего символа.
Нормализация освобождает нас от необходимости убедиться , что все суммы до некоторого значения. После нормализации "вектор" вероятностей суммируется до 1.0.
Остальная часть кода для выбора и генерации произвольной длины образца от распределения ниже:
Использование :
источник
Вот более эффективный способ сделать это:
Просто вызовите следующую функцию со своим массивом «weights» (при условии, что индексы являются соответствующими элементами) и значением no. необходимых образцов. Эту функцию можно легко изменить для обработки упорядоченной пары.
Возвращает индексы (или элементы), отобранные / выбранные (с заменой), используя их соответствующие вероятности:
Краткое замечание о концепции, используемой в цикле while. Мы уменьшаем вес текущего элемента из кумулятивного бета, который представляет собой кумулятивное значение, построенное равномерно случайным образом, и увеличиваем текущий индекс, чтобы найти элемент, вес которого соответствует значению бета.
источник