Keine dieser Antworten ist besonders klar oder einfach.
Hier ist eine klare, einfache Methode, die garantiert funktioniert.
accumulate_normalize_probabilities verwendet ein Wörterbuch p
, das Symbole Wahrscheinlichkeiten ODER Frequenzen zuordnet . Es gibt eine verwendbare Liste von Tupeln aus, aus denen ausgewählt werden kann.
def accumulate_normalize_values(p):
pi = p.items() if isinstance(p,dict) else p
accum_pi = []
accum = 0
for i in pi:
accum_pi.append((i[0],i[1]+accum))
accum += i[1]
if accum == 0:
raise Exception( "You are about to explode the universe. Continue ? Y/N " )
normed_a = []
for a in accum_pi:
normed_a.append((a[0],a[1]*1.0/accum))
return normed_a
Ausbeuten:
>>> accumulate_normalize_values( { 'a': 100, 'b' : 300, 'c' : 400, 'd' : 200 } )
[('a', 0.1), ('c', 0.5), ('b', 0.8), ('d', 1.0)]
Warum es funktioniert
Die Akkumulation verwandelt jedes Symbol in ein Intervall zwischen sich und der Wahrscheinlichkeit oder Häufigkeit der vorherigen Symbole (oder 0 im Fall des ersten Symbols). Diese Intervalle können verwendet werden, um aus der Liste auszuwählen (und damit die bereitgestellte Verteilung abzutasten), indem Sie einfach durch die Liste gehen, bis die Zufallszahl in Intervall 0.0 -> 1.0 (zuvor vorbereitet) kleiner oder gleich dem Intervallendpunkt des aktuellen Symbols ist.
Das Normalisierung befreit uns von der Notwendigkeit, sicherzustellen, dass alles einen gewissen Wert hat. Nach der Normalisierung summiert sich der "Vektor" der Wahrscheinlichkeiten auf 1,0.
Der Rest des Codes zum Auswählen und Generieren einer beliebig langen Stichprobe aus der Verteilung ist unten aufgeführt:
def select(symbol_intervals,random):
print symbol_intervals,random
i = 0
while random > symbol_intervals[i][1]:
i += 1
if i >= len(symbol_intervals):
raise Exception( "What did you DO to that poor list?" )
return symbol_intervals[i][0]
def gen_random(alphabet,length,probabilities=None):
from random import random
from itertools import repeat
if probabilities is None:
probabilities = dict(zip(alphabet,repeat(1.0)))
elif len(probabilities) > 0 and isinstance(probabilities[0],(int,long,float)):
probabilities = dict(zip(alphabet,probabilities)) #ordered
usable_probabilities = accumulate_normalize_values(probabilities)
gen = []
while len(gen) < length:
gen.append(select(usable_probabilities,random()))
return gen
Verwendung :
>>> gen_random (['a','b','c','d'],10,[100,300,400,200])
['d', 'b', 'b', 'a', 'c', 'c', 'b', 'c', 'c', 'c'] #<--- some of the time
random.choice()
? Sie erstellen die Hauptliste mit der richtigen Anzahl von Vorkommen und wählen eines aus. Dies ist natürlich eine doppelte Frage.