О том, как работает numpy.random.choice - PullRequest
0 голосов
/ 25 ноября 2018

Я пытаюсь написать программу, которая имитирует проблему Купона .Вот краткое описание проблемы:

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

Я придумал две части кода:

(1)

n = 50
coupon = np.arange(0, n)
def collect(coupon):
    number = 49
    collection = np.array([])
    while len(set(collection)) != n:
          number +=1
          collection = np.random.choice(coupon, replace = True, size = number)
    return number

И получил результат за 10 итераций сбора (купона) со средним значением::

[175. 151. 128. 132. 169. 118. 134. 138. 150. 135.]
143.0

(2)

n = 50
coupon = np.arange(0,n)
def collect(coupon):
    collection = set()
    number = 0
    while len(collection) != n:
          number +=1
          got = np.random.choice(coupon)
          collection.add(got)
    return number

Результат выполнения 10 итераций сбора (купона) со средним значением:

[184, 119, 286, 196, 172, 370, 163, 267, 238, 199]
219.4

Я пыталсядля большого количества взаимодействий код (1) и код (2) дают очень разные результаты.

Я знаю, что правильный ответ для ожидаемого значения для сбора всех 50 купонов - 225, а код (2) - правильный.С другой стороны, я не могу найти разумного объяснения, почему код (1) не работает?Почему numpy.random.choice не работает в этом примере?

1 Ответ

0 голосов
/ 25 ноября 2018

Неполные проблемы (или нет)

Ваш код выглядит нормально, включая использование np.random.choice.Возможно, возникла путаница, связанная со значением по умолчанию параметра replace.replace по умолчанию True, поэтому вам не нужно явно передавать replace = True в choice в блоке кода (1).

Помимо этой очень незначительной проблемы, нет явных проблем сваш код.Таким образом, проблема может заключаться в математике и вероятности.

Проблемы вероятности

225 - это ожидаемое значение, когда размер ничьи равен 1. В вашем коде (1) размер ничьи увеличиваетсяс каждой итерацией.Подумайте об этом следующим образом: с увеличением размера тиража шансы получить все купоны за один тираж начинают становиться достаточно большими.Я не знаю точного числа ( РЕДАКТИРОВАТЬ: я нашел несколько точных чисел. Теперь они находятся в разделе «Более глубокое расследование» ниже ), но говорят, что вероятность получения всех 50 купонов в одномничья 100 - 0,01.К тому времени, когда вы начнете рисовать 143, кумулятивные шансы получить все купоны хотя бы один раз должны быть не менее 0,4 (и, вероятно, больше).

Более глубокое исследование

СНесколько твиков, ваш код может быть использован для оценки шансов увидеть все 50 купонов в одном розыгрыше размером x:

def collectx(coupon, x, reps):
    x = np.asarray(x)
    n = coupon.size

    counts = np.zeros((x.size, reps), dtype=int)
    for i,xsub in enumerate(x):
        for j in range(reps):
            count = 1
            while np.unique(np.random.choice(coupon, size=xsub)).size < n:
                count += 1
            counts[i, j] = count

    return counts

Вероятности для многих различных значений x можно оценить сразу, передавв последовательности.Теперь, чтобы оценить вероятности для всех размеров рисования 120-143, вы можете выполнить:

n = 50
coupon = np.arange(0, n)
counts = collectx(coupon, np.arange(120,144), 100)

Это дает counts, который является массивом формы (24, 100).Размер чертежа варьируется в зависимости от строк, а идентификатор репликации оценки зависит от столбцов.Вы можете получить вероятности «увидеть каждый купон в одном розыгрыше», взяв среднее по повторным оценкам и разделив результат на 1:

probx = (1/counts.mean(axis=1))

, который выглядит следующим образом:

[0.00418971 0.00563    0.00661288 0.00694493 0.00690799 0.00854774
 0.00909339 0.01050531 0.01207875 0.01344086 0.01485222 0.0155642
 0.02004008 0.02115059 0.02015723 0.02377556 0.02639916 0.02379819
 0.02856327 0.03941663 0.04145937 0.03162555 0.03601008 0.04821601]

При размере ничьей в 120 вероятность все еще ниже 0,005, но она быстро увеличивается, а при размере ничьи 143 вероятность увидеть каждый купон составляет почти 0,05.Поскольку вероятности для размеров розыгрыша ниже 120 малы, суммирование по вероятностям размеров розыгрыша 120-143 дает разумную оценку совокупной вероятности того, что ваш кодовый блок (1) видел все купоны в одном розыгрыше к моменту его завершения сразмер розыгрыша 143:

print('%.3f' % probx.sum())

Вывод:

0.475

Таким образом, ваш кодовый блок (1) с большой вероятностью не видел бы каждый купон при n==143.Что полностью соответствует результатам, которые вы наблюдали.Так что никаких проблем с Numpy, просто одна вероятность.

...