Взвешивание различных результатов при псевдослучайном выборе из произвольно большой выборки - PullRequest
1 голос
/ 14 сентября 2010

Итак, я сидел на своем заднем дворе, думая о покемонах, как мы все привыкли делать, и это заставило меня задуматься: когда вы встречаете «случайного» покемона, некоторые экземпляры появляются намного чаще, чем другие, что означает, что они имеют вес, отличный от тех, которые отображаются меньше.

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

Pool:
C1 C1 C1 C1
C2 C2
C3 C3 C3 C3 C3
C4

таким образом, у C1 есть шанс 1/3, у C2 - 1/6, и т. Д., Но я понимаю, что это может быть очень простой и наивный подход, и вряд ли он хорошо масштабируется при большом количестве выбор.

Итак, мой вопрос таков: S / O: Учитывая произвольно большой размер выборки, как бы вы оценили вероятность того, что один исход будет больше другого? И, в качестве последующего вопроса, предположим, что вы хотите, чтобы вероятность определенных опционов возникала в соотношении с точностью с плавающей запятой, а не в отношении целых чисел?

1 Ответ

1 голос
/ 14 сентября 2010

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

Итак, в приведенном выше примере 12 Cs. С1 составляет 4/12 или ~ 33%, C2 составляет 2/12 от ~ 17%, C3 составляет 5/12 или ~ 42% и C4 составляет 1/12 или ~ 8%.

Обратите внимание, что все это составляет до 100%. Поэтому, если мы выберем случайное число от 0 до 100, мы можем отобразить C1 на 0-33, C2 на 33-50 (на 17 больше значения C1), C3 на 50-92 и C4 на 92-100.

Оператор if может сделать выбор:

r = rand() # between 0-100
if (r <33)
  return "C1"
elsif (r < 50)
  return "C2"
elsif (r < 92)
  return "C3"
elsif (r < 100)
  return "C4"

Если вы хотели больше точности, чем 1 из 100, просто перейдите от 1 до 1000 или любого другого диапазона. Вероятно, лучше использовать целые числа и масштабировать их, чем использовать числа с плавающей запятой, поскольку с плавающей запятой может возникнуть странное поведение, если разброс между значениями становится большим.

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

a = ["C1"]*4 + ["C2"]*2 + ["C3"]*5 + ["C4"]
# ["C1", "C1", "C1", "C1", "C2", "C2", 
#  "C3", "C3", "C3", "C3", "C3", "C4"]
a[rand(a.length)] # => "C1' w/ probability 4/12

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

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

...