L'un des moyens les plus rapides de créer de nombreux échantillons avec remplacement à partir d'une liste immuable est la méthode des alias. L'intuition de base est que nous pouvons créer un ensemble de cases de taille égale pour la liste pondérée qui peut être indexée très efficacement par des opérations sur les bits, afin d'éviter une recherche binaire. Il s'avérera que, si l'on procède correctement, nous n'aurons besoin de stocker que deux éléments de la liste originale par bac, et nous pourrons donc représenter la division avec un seul pourcentage.
Prenons l'exemple de cinq choix à pondération égale, (a:1, b:1, c:1, d:1, e:1)
Pour créer la recherche d'alias :
-
Normaliser les poids de sorte que leur somme soit égale à 1.0
. (a:0.2 b:0.2 c:0.2 d:0.2 e:0.2)
C'est la probabilité de choisir chaque poids.
-
Trouvez la plus petite puissance de 2 supérieure ou égale au nombre de variables, et créez ce nombre de partitions, |p|
. Chaque partition représente une masse de probabilité de 1/|p|
. Dans ce cas, nous créons 8
partitions, chacune pouvant contenir 0.125
.
-
Prenez la variable ayant le moins de poids restant, et placez autant de sa masse que possible dans une partition vide. Dans cet exemple, nous voyons que a
remplit la première partition. (p1{a|null,1.0},p2,p3,p4,p5,p6,p7,p8)
con (a:0.075, b:0.2 c:0.2 d:0.2 e:0.2)
-
Si la partition n'est pas remplie, prenez la variable ayant le plus de poids, et remplissez la partition avec cette variable.
Répétez les étapes 3 et 4, jusqu'à ce qu'aucun des poids de la partition d'origine n'ait besoin d'être affecté à la liste.
Par exemple, si nous exécutons une autre itération de 3 et 4, nous voyons
(p1{a|null,1.0},p2{a|b,0.6},p3,p4,p5,p6,p7,p8)
con (a:0, b:0.15 c:0.2 d:0.2 e:0.2)
restant à attribuer
En cours d'exécution :
-
Obtenir un U(0,1)
un nombre aléatoire, disons binaire 0.001100000
-
le bithift lg2(p)
en trouvant la partition de l'indice. Ainsi, nous le décalons de 3
ce qui donne 001.1
ou la position 1, et donc la partition 2.
-
Si la partition est divisée, utilisez la partie décimale du nombre aléatoire décalé pour décider de la division. Dans ce cas, la valeur est 0.5
y 0.5 < 0.6
donc retour a
.
Voici un peu de code et une autre explication mais malheureusement, il n'utilise pas la technique du bithifting, et je ne l'ai pas vérifié.
0 votes
Voir cette question stackoverflow.com/q/10164303/112100 même si c'est du C# et non du python, il y a très peu de code et tout le monde peut le comprendre.
1 votes
Pour tous ceux qui ont dû chercher, l'"algorithme du réservoir" se trouve sur Wikipédia, sous la rubrique "". échantillonnage de réservoirs ". Le premier article cité est celui de Jeffrey Scott Vitter "Random Sampling with a Reservoir", tiré de ACM Transactions on Mathematical Software , Vol. 11, No. 1, 01 Mar 1985, pp. 37--57.
0 votes
Pour la pondération sans remplacement, où le poids signifie que la probabilité d'être choisi est proportionnelle au poids, voir ma réponse ici : stackoverflow.com/a/27049669/262304 Notez que certaines entrées n'ont pas de solution, par exemple, choisir 2 parmi {'a' : 3, 'b' : 1, 'c : 1} devrait donner 'a' 3x plus souvent que b ou c, mais c'est impossible.