Ошибка распределения случайного выбора - PullRequest
0 голосов
/ 02 мая 2018

У меня есть список чисел и другой список вероятностей, который соответствует этим числам. Я использую numpy.random.choice для создания случайного 2d массива:

choice = numpy.random.choice([10, 22, 30], [10, 10], p=[0.45, 0.45, 0.10])

В choice должно быть 45 единиц, 45 двойок и 10 нулей, но после нескольких прогонов я никогда не получу правильное распределение.

unique, counts = numpy.unique(choice, return_counts=True)
print(dict(zip(unique, counts)))

{10: 49, 22: 37, 30: 14}
{10: 47, 22: 42, 30: 11}
{10: 40, 22: 51, 30: 9}

Что я пропустил?

Ответы [ 4 ]

0 голосов
/ 02 мая 2018

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

import numpy
import numpy.random

numbers = numpy.asarray(45*[10]+45*[22]+10*[30])
print (numbers)
numpy.random.shuffle(numbers) # numbers is changed in place
choice = numbers.reshape((10,10))

print (choice)
unique, counts = numpy.unique(choice, return_counts=True)
print(dict(zip(unique, counts)))
0 голосов
/ 02 мая 2018

То есть, если вы перевернули монетку тысячу раз, вы бы ожидали, что всегда получат ровно 500 голов?

Если вы хотите контролировать точное количество каждого результата, вы не можете полагаться на вероятности - вместо этого выберите (без замены) из списка, в котором каждый результат присутствует с желаемой кратностью:

numpy.random.choice([10] * 45 + [22] * 45 + [30] * 10, [10, 10], replace=False)
0 голосов
/ 02 мая 2018

То, что сказал Матиас, верно.

Если вы хотите создать массив из ровно 45 нулей, 45 единиц и 10 двойок, имеющих форму (10, 10), но в случайном порядке, вы можете сделать что-то вроде этого:

import numpy as np
zeros = np.array([0]*45)
ones = np.array([1]*45)
twos = np.array([2]*10)
myarr = np.concatenate([zeros, ones, twos])

# Random permutation, followed by reshaping in (10, 10) form
choice = np.random.permutation(myarr).reshape(10,10)
unique, counts = np.unique(choice, return_counts=True)
print(dict(zip(unique, counts)))
{0: 45, 1: 45, 2: 10}
0 голосов
/ 02 мая 2018

Вам совершенно не хватает того, как на практике работает выборка из дистрибутива. Вы никогда не «получаете» правильное распределение, вы всегда получаете приближение к нему, потому что вы делаете выборку.

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

И это, конечно, относится к генерации чисел с (псевдо) генератором случайных чисел.

...