2010-12-14 16 views
14

He estado tratando de codificar un programa que usa la función de activación de softmax en el medio.Elija la variable de lista dada la probabilidad de cada variable

En este momento, tengo una lista de probabilidades como esto:

P[0.10,0.25,0.60,0.05] 

La suma de todas las variables en P es siempre 1.

Yo quería una forma de escoger el índice de la lista dada la probabilidad que se le atribuye. O, en otras palabras, una función que devuelve

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

tengo ni idea de por dónde empezar en esto. Cualquier ayuda sería apreciada. :)

Respuesta

10

Hmm interesante, ¿qué tal ...

  1. generar un número entre 0 y 1.

  2. Camina la lista restando la probabilidad de cada artículo de su número.

  3. Elija el elemento que, después de la resta, llevó su número a 0 o menos.

que es simple, O (n) y debería funcionar :)

2
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 
+0

Jaja Y yo que pensaba ~ 2 segundos antes informados de que estaba siendo originales – slezica

+0

@Santiago: y me preguntó por qué las ha escrito en Inglés :) – sje397

10

Básicamente, haga una matriz cumulative probability distribution (CDF). Básicamente, el valor de la CDF para un índice dado es igual a la suma de todos los valores en P igual o menor que ese índice. Luego generas un número aleatorio entre 0 y 1 y haces una búsqueda binaria (o búsqueda lineal si quieres). Aquí hay un código simple para eso.

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()) 

, por supuesto, se puede generar un montón de índices aleatorios con algo así como

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

rendimiento

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

(resultados, y debe variar). Por supuesto, la búsqueda binaria es bastante innecesaria para tan pocos índices posibles, pero definitivamente se recomienda para distribuciones con más índices posibles.

+0

Eso es bueno .... – sje397

3

Este problema es equivalente al muestreo de un categorical distribution. Esta distribución se combina comúnmente con la distribución multinomial que modela el resultado de múltiples muestras de una distribución categórica.

En numpy, es fácil muestrear de la distribución multinomial usando numpy.random.multinomial, pero no existe una versión categórica específica de esto. Sin embargo, puede lograrse muestreando desde la distribución multinomial con una única prueba y luego devolviendo el elemento distinto de cero en la salida.

import numpy as np 
pvals = [0.10,0.25,0.60,0.05] 
ind = np.where(np.random.multinomial(1,pvals))[0][0] 
15

Esto se puede lograr fácilmente con numpy. Tiene una función choice que acepta el parámetro de probabilidades.

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