Ошибка распределения случайного выбора Numpy
У меня есть список чисел и другой список вероятностей, который соответствует этим числам. Я использую 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 ответа:
То есть, если вы бросите монету тысячу раз, вы ожидаете, что всегда получите ровно 500 голов?
Если вы хотите контролировать точное количество каждого результата, вы не можете полагаться на вероятности-вместо этого выберите (без замены) из списка, в котором каждый результат присутствует с желаемой кратностью:numpy.random.choice([10] * 45 + [22] * 45 + [30] * 10, [10, 10], replace=False)
Вы полностью упускаете из виду, как выборка из распределения работает на практике. Вы никогда не "получаете" правильное распределение, вы всегда получаете приближение к нему, потому что вы делаете выборку.
Только в том случае, когда число выборок очень велико, вы должны в конечном итоге сходиться к целевому распределению. Но так как выборка-это стохастический процесс, то в результатах этого процесса всегда присутствует случайность.
И это, конечно, относится к генерации чисел с a (псевдо-)генератор случайных чисел.
То, что сказал Матиас, - правда.
Если вы хотите создать массив с ровно 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}
Выборка не будет точной, вы можете заставить все числа быть в выходном массиве, составив список всех чисел, которые вы хотите, а затем случайным образом перемешать его:
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)))