Случайный выбор с условными вероятностями - PullRequest
1 голос
/ 28 июня 2019

У меня есть список, скажем y = [1, 2, 3, 4, 6, 7, 8, 9, 5, 23, 12, 24, 43, 10], и я хочу сделать из него случайный выбор с условной вероятностью.Число, большее 10 в списке, имеет вероятность, например, 0,8 быть выбранным, в то время как остальные имеют вероятность 0,2 выбора.

Ответы [ 2 ]

2 голосов
/ 28 июня 2019

Поскольку random.choice обеспечивает равномерное распределение, вам придется работать в два этапа. Сначала выберите между группами значений (ниже 10 и выше 10). Затем выберите значение в группе.

Чтобы получить разные вероятности между группами, вы можете создать список с соответствующим количеством повторений для каждой группы. Например, для 0,2 и 0,8 у вас будет 2 экземпляра группы «ниже10» и 8 экземпляров группы «выше10» в списке. Это преобразует регулярное распределение во взвешенное распределение относительно каждой группы.

import random

treshold = 10
y       = [1, 2, 3, 4, 6, 7, 8, 9, 5, 23, 12, 24, 43, 10]
group1  = [v for v in y if v <  treshold]
group2  = [v for v in y if v >= treshold]

def getValue():
    group = random.choice([group1]*2 + [group2]*8)
    return random.choice(group)

Чтобы проверить, соответствует ли распределение требованиям, вы можете использовать функцию большое количество раз и рассчитать, сколько раз было выбрано значение в каждой группе.

lowCount  = 0
highCount = 0
N         = 10000
for _ in range(N):
    v = getValue()
    if v < treshold:
        lowCount += 1
    else:
        highCount += 1
print(round(lowCount/N,2),round(highCount/N,2))

# 0.2 0.8

Если у вас есть только 2 группы, вы можете использовать простой оператор if-else для выбора:

def getValue():
    return random.choice(group1) if random.random() <= 0.2 else random.choice(group2)

РЕДАКТИРОВАТЬ Для одного значения (скажем, 23) с вероятностью 0,9 подход такой же:

y       = [1, 2, 3, 4, 6, 7, 8, 9, 5, 23, 12, 24, 43, 10]
group1  = [23]
group2  = [v for v in y if v not in group1]
def getValue():
    return random.choice(group1) if random.random() <= 0.9 else random.choice(group2)

lowCount  = 0
highCount = 0
N         = 10000
for _ in range(N):
    v = getValue()
    if v == 23:        # <== same condition as the grouping rule.
        lowCount += 1
    else:
        highCount += 1
print(round(lowCount/N,2),round(highCount/N,2))

# 0.9 0.1

Однако вы должны соответствующим образом настроить цикл тестирования

1 голос
/ 28 июня 2019

попробуйте это: он использует np.random.choice из списка, состоящего из элементов со списком, который содержит propabilité каждого элемента цикла for, который сгенерирует этот список из списка ввода:

import numpy as np
y = [1, 2, 3, 4, 6, 7, 8, 9, 5, 23, 12, 24, 43, 10]
t=[]
sup=0
inf=0
for j in y:
    if j>10:
        sup=sup+1
    else:
        inf=inf+1
print(sup)
print(inf)
p=[]
for i in y:
    if i>10:
        p.append(1/sup)
    else:
        p.append(0/inf)
print(p)
x=np.random.choice(y, 100, p=p)

print(x)

output

[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.25, 0.25, 0.25, 0.25, 0.0]
[12 23 23 43 23 12 12 43 24 12]

другой выход с вероятностью 0,5 и 0,5:

[0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.125, 0.125, 0.125, 0.125, 0.05]
[24 24 43  8  4 12 23 24  6  5]

другой выход с:

[0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.2, 0.2, 0.2, 0.2, 0.02]
[24 43 23 24  7 24 12 12 43 24]
...