recommendation engine algorithms python algorithm round-robin

engine - Python Weighted Random



recommendation system pandas (4)

Parece correcto, ya que está utilizando una variable aleatoria uniform con sorteos independientes, la probabilidad de cada número será 1/n (n = 100).

Puede verificar fácilmente su algoritmo ejecutándolo diga 1000 veces y ver la frecuencia de cada letra.

Otro algoritmo que podría considerar es generar una matriz con sus letras dada la frecuencia que desea para cada letra y solo generar un único número aleatorio que sea el índice en la matriz

Será menos eficiente en la memoria pero debería funcionar mejor

Editar:

Para responder al comentario de @Joel Cornett, un ejemplo será muy similar a @jurgenreza pero más eficiente en memoria

import random data_list = [''A''] + [''B''] + [''C''] * 18 random.choice(data_list )

Esta pregunta ya tiene una respuesta aquí:

Necesito devolver valores diferentes según un round-robin ponderado, de modo que 1 de cada 20 obtenga A, 1 de 20 obtenga B, y el resto vaya a C.

Asi que:

A => 5% B => 5% C => 90%

Aquí hay una versión básica que parece funcionar:

import random x = random.randint(1, 100) if x <= 5: return ''A'' elif x > 5 and x <= 10: return ''B'' else: return ''C''

¿Es este algoritmo correcto? Si es así, ¿se puede mejorar?


Si desea utilizar aleatorios ponderados y no aleatorios de percentiles, puede crear su propia clase de Randomizer:

import random class WeightedRandomizer: def __init__ (self, weights): self.__max = .0 self.__weights = [] for value, weight in weights.items (): self.__max += weight self.__weights.append ( (self.__max, value) ) def random (self): r = random.random () * self.__max for ceil, value in self.__weights: if ceil > r: return value w = {''A'': 1.0, ''B'': 1.0, ''C'': 18.0} #or w = {''A'': 5, ''B'': 5, ''C'': 90} #or w = {''A'': 1.0/18, ''B'': 1.0/18, ''C'': 1.0} #or or or wr = WeightedRandomizer (w) results = {''A'': 0, ''B'': 0, ''C'': 0} for i in range (10000): results [wr.random () ] += 1 print (''After 10000 rounds the distribution is:'') print (results)


Su algoritmo es correcto, ¿qué tal algo más elegante:

import random my_list = [''A''] * 5 + [''B''] * 5 + [''C''] * 90 random.choice(my_list)


esta bien. De manera más general, puedes definir algo como:

from collections import Counter from random import randint def weighted_random(pairs): total = sum(pair[0] for pair in pairs) r = randint(1, total) for (weight, value) in pairs: r -= weight if r <= 0: return value results = Counter(weighted_random([(1,''a''),(1,''b''),(18,''c'')]) for _ in range(20000)) print(results)

lo que da

Counter({''c'': 17954, ''b'': 1039, ''a'': 1007})

que es lo más cercano a 18: 1: 1 que puede esperar.