web-dev-qa-db-fra.com

Choisissez une variable de liste en fonction de la probabilité de chaque variable

J'ai essayé de coder un programme qui utilise la fonction d'activation softmax au milieu.

En ce moment, j'ai une liste de probabilités comme celle-ci:

P[0.10,0.25,0.60,0.05]

La somme de toutes les variables dans P est toujours 1.

Je voulais un moyen de choisir l'index de la liste compte tenu de la probabilité qui s'y rattache. Ou, en d'autres termes, une fonction qui a renvoyé

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

Je ne sais absolument pas par où commencer. Toute aide serait appréciée. :)

30
Roughmar

Vous pouvez facilement y parvenir avec numpy. Il a une fonction choix qui accepte le paramètre de probabilités.

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

Fondamentalement, créez un tableau distribution de probabilité cumulée (CDF). Fondamentalement, la valeur du CDF pour un indice donné est égale à la somme de toutes les valeurs de P égales ou inférieures à cet indice. Ensuite, vous générez un nombre aléatoire entre 0 et 1 et effectuez une recherche binaire (ou une recherche linéaire si vous le souhaitez). Voici un code simple pour cela.

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

bien sûr, vous pouvez générer un tas d'indices aléatoires avec quelque chose comme

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

céder

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

(les résultats varieront et devraient varier). Bien sûr, la recherche binaire est plutôt inutile pour si peu d'indices possibles, mais certainement recommandée pour les distributions avec plus d'indices possibles.

11
Justin Peel

Hmm intéressant, que diriez-vous ...

  1. Générez un nombre compris entre 0 et 1.

  2. Parcourez la liste en soustrayant la probabilité de chaque élément de votre numéro.

  3. Choisissez l'élément qui, après soustraction, a réduit votre nombre à 0 ou en dessous.

C'est simple, O(n) et devrait fonctionner :)

10
slezica

Ce problème équivaut à l'échantillonnage à partir d'une distribution catégorielle . Cette distribution est généralement confondue avec la distribution multinomiale qui modélise le résultat de plusieurs échantillons d'une distribution catégorielle.

Dans numpy, il est facile d'échantillonner à partir de la distribution multinomiale en utilisant numpy.random.multinomial , mais il n'existe pas de version catégorique spécifique de cela. Cependant, cela peut être accompli en échantillonnant à partir de la distribution multinomiale avec un seul essai puis en renvoyant l'élément non nul dans la sortie.

import numpy as np
pvals = [0.10,0.25,0.60,0.05]
ind = np.where(np.random.multinomial(1,pvals))[0][0]
4
animus144
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
2
sje397