Выберите переменную списка с учетом вероятности каждой переменной

Я пытаюсь закодировать программу, которая использует функцию активации 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

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

Ответ 1

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

np.random.choice(
  ['pooh', 'rabbit', 'piglet', 'Christopher'], 
  5,
  p=[0.5, 0.1, 0.1, 0.3]
)

Ответ 2

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

  • Создайте число от 0 до 1.

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

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

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

Ответ 3

В принципе, создайте массив совокупное распределение вероятности (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)]

получая

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

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

Ответ 5

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

В 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]

Ответ 6

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