Выберите переменную списка с учетом вероятности каждой переменной - PullRequest
23 голосов
/ 14 декабря 2010

Я пытался закодировать программу, которая использует функцию активации softmax посередине.

Сейчас у меня есть список вероятностей, подобный этому:

P[0.10,0.25,0.60,0.05]

сумма всех переменных в P всегда равна 1.

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

0 - 10% of the time
1 - 25% of the time
2 - 60% of the time
3 - 5% of the time

Я абсолютно не знаю, с чего начать.Любая помощь будет оценена.:)

Ответы [ 6 ]

37 голосов
/ 12 ноября 2016

Вы можете легко достичь этого с NumPy. Он имеет функцию choice , которая принимает параметр вероятностей.

np.random.choice(
  ['pooh', 'rabbit', 'piglet', 'Christopher'], 
  5,
  p=[0.5, 0.1, 0.1, 0.3]
)
11 голосов
/ 14 декабря 2010

По существу, создайте массив кумулятивного распределения вероятностей (CDF). По сути, значение CDF для данного индекса равно сумме всех значений в P, равной или меньшей этого индекса. Затем вы генерируете случайное число от 0 до 1 и выполняете двоичный поиск (или, если хотите, линейный поиск). Вот простой код для этого.

from bisect import bisect
from random import random

P = [0.10,0.25,0.60,0.05]

cdf = [P[0]]
for i in xrange(1, len(P)):
    cdf.append(cdf[-1] + P[i])

random_ind = bisect(cdf,random())

конечно, вы можете генерировать кучу случайных индексов с чем-то вроде

rs = [bisect(cdf, random()) for i in xrange(20)]

* 1009 получая *

[2, 2, 3, 2, 2, 1, 2, 2, 2, 1, 2, 1, 2, 1, 2, 1, 2, 2, 2, 2]

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

10 голосов
/ 14 декабря 2010

Хм, интересно, как насчет ...

  1. Генерировать число от 0 до 1.

  2. Пройтись по списку, вычтя вероятностькаждый предмет с вашего номера.

  3. Выберите предмет, который после вычитания опустил ваш номер до 0 или ниже.

Это просто,O (n) и должно работать:)

4 голосов
/ 17 мая 2014

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

В numpy легко получить выборку из полиномиального распределения, используя numpy.random.multinomial , но конкретной категориальной версии этого не существует. Тем не менее, это может быть достигнуто путем выборки из полиномиального распределения с одним испытанием, а затем возвращая ненулевой элемент на выходе.

import numpy as np
pvals = [0.10,0.25,0.60,0.05]
ind = np.where(np.random.multinomial(1,pvals))[0][0]
4 голосов
/ 14 декабря 2010

То, что вы ищете, это взвешенное случайное поколение, и хотя оно не является встроенным, существует множество стандартных рецептов для этого .

2 голосов
/ 14 декабря 2010
import random

probs = [0.1, 0.25, 0.6, 0.05]
r = random.random()
index = 0
while(r >= 0 and index < len(probs)):
  r -= probs[index]
  index += 1
print index - 1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...