Взвешенный выбор в Numpy не возвращает список с точной вероятностью ввода - PullRequest
0 голосов
/ 13 сентября 2018

У меня есть список объектов ['P1', 'P2', 'P3'] с [0.8,0.1,0.1] в качестве соответствующих весов.

Я обнаружил, что при выборе значения numpy в качестве входного значения используется вес, но я не вижу, чтобы выходной список точно совпадал с вероятностью ввода

Код:

draw = [choice(['P1','P2','P3'],p=[0.8,0.1,0.1]) for _ in range(10)]
from collections import Counter
print(Counter(draw))

Я ожидал, что дро будет всегда содержать 8 экземпляров P1, 1 из P2 и 1 из P3.

Но я вижу, что он меняется от запуска к запуску при использовании приведенного выше кода.

Пример вывода:

Run 1:
Counter({'P1': 7, 'P2': 2, 'P3': 1})

Run 2:
Counter({'P1': 10})

Run 3:
Counter({'P1': 9, 'P2': 1})

Я что-то упустил или это ожидаемый результат?

Ответы [ 2 ]

0 голосов
/ 13 сентября 2018

используйте np.repeat и np.random.shuffle

def draw(elements, counts):
    out =  np.repeat(elements, counts)
    np.random.shuffle(out)
    return out

draw(['P1','P2', 'P3'], [8,1,1])
Out: 
array(['P1', 'P3', 'P2', 'P1', 'P1', 'P1', 'P1', 'P1', 'P1', 'P1'], 
      dtype='<U2')
0 голосов
/ 13 сентября 2018

Документация из numpy.random.choice говорит вам, что аргумент p - это вероятности, связанные с каждой записью. И если не дано, предполагается равномерная вероятность.

Равномерная вероятность означает, что вероятность выбора любого из предметов равна. Но это не значит, что количество результатов будет пропорционально вероятности всегда .

Пример: при подбрасывании монеты вероятность получить голову равна вероятности получить хвост. Но всегда ли я получу 5 голов и 5 хвостов, когда брошу 10 раз? Нет.

toss=[np.random.choice(["head","tail"]) for _ in range(10)]
print(Counter(toss)) #Counter({'head': 7, 'tail': 3})

Точно так же в вашем случае вы только упомянули, что вероятность получения P1 равна 0,8, но это не значит, что вы всегда будете видеть 8 P1 с при случайном выборе 10 раз, это только означает, что вероятность получения это значительно выше, чем у остальных.

РЕДАКТИРОВАТЬ :

Чтобы получить необходимую вам функциональность, вы можете написать функцию, которая копирует элемент списка. Учитывая вероятность (p = 0,8) и общее количество элементов (n = 10), количество повторений должно составлять p*n

def MyDist(elements,weights,num):
    a=[]
    for i in range(len(elements)):
        a+=[elements[i]]*int(weights[i]*num)
    return a

MyDist(['P1','P2','P3'],[0.8,0.1,0.1],10)
#['P1', 'P1', 'P1', 'P1', 'P1', 'P1', 'P1', 'P1', 'P2', 'P3']
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...