np.random.choice:概率不总和为1

时间:2017-10-03 07:36:21

标签: python numpy

我如何在这里使用np.random.choice?p通过某些操作来计算,例如:

 p=[  1.42836755e-01,   1.42836735e-01  , 1.42836735e-01,   1.42836735e-01
,   4.76122449e-05,   1.42836735e-01  , 4.76122449e-05  , 1.42836735e-01,
   1.42836735e-01,   4.76122449e-05]

通常和p不完全等于1:

>>> sum(p)
1.0000000017347

我想通过概率= p:

进行随机选择
>>> np.random.choice([1,2,3,4,5,6,7,8,9, 10], 4, p=p, replace=False)
array([4, 3, 2, 9])

这个工作在这里!但在程序中它有一个错误:

Traceback (most recent call last):
    indexs=np.random.choice(range(len(population)), population_number, p=p, replace=False)
  File "mtrand.pyx", line 1141, in mtrand.RandomState.choice (numpy/random/mtrand/mtrand.c:17808)
ValueError: probabilities do not sum to 1

如果我打印p

[  4.17187500e-05   2.49937500e-01   4.16562500e-05   4.16562500e-05
   2.49937500e-01   4.16562500e-05   4.16562500e-05   4.16562500e-05
   2.49937500e-01   2.49937500e-01]

但它可以在python shell中使用p

>>> p=[  4.17187500e-05 ,  2.49937500e-01   ,4.16562500e-05  , 4.16562500e-05,
   2.49937500e-01  , 4.16562500e-05  , 4.16562500e-05  , 4.16562500e-05,
   2.49937500e-01   ,2.49937500e-01]
>>> np.random.choice([1,2,3,4,5,6,7,8,9, 10], 4, p=p, replace=False)
array([ 9, 10,  2,  5])

更新 我已经通过precision = 15测试了它:

 np.set_printoptions(precision=15)
 print(p)
[  2.499375625000002e-01   2.499375000000000e-01   2.499375000000000e-01
   4.165625000000000e-05   4.165625000000000e-05   4.165625000000000e-05
   4.165625000000000e-05   4.165625000000000e-05   2.499375000000000e-01
   4.165625000000000e-05]

测试:

>>> p=np.array([  2.499375625000002e-01   ,2.499375000000000e-01   ,2.499375000000000e-01,
   4.165625000000000e-05   ,4.165625000000000e-05,   4.165625000000000e-05,
   4.165625000000000e-05  , 4.165625000000000e-05 ,  2.499375000000000e-01,
   4.165625000000000e-05])
>>> np.sum(p)
1.0000000000000002

如何修复此问题以使用np.random.choice?

4 个答案:

答案 0 :(得分:7)

这是一个带有numpy的known issue。随机选择函数使用给定的容差(here the source

检查概率的总和

解决方案是通过将概率除以它们的总和来归一化概率,如果总和足够接近1

示例:

>>> p=[  1.42836755e-01,   1.42836735e-01  , 1.42836735e-01,   1.42836735e-01
,   4.76122449e-05,   1.42836735e-01  , 4.76122449e-05  , 1.42836735e-01,
   1.42836735e-01,   4.79122449e-05]
>>> sum(p) 
1.0000003017347 # over tolerance limit
>>> np.random.choice([1,2,3,4,5,6,7,8,9, 10], 4, p=p, replace=False)

Traceback (most recent call last):
  File "<pyshell#23>", line 1, in <module>
    np.random.choice([1,2,3,4,5,6,7,8,9, 10], 4, p=p, replace=False)
  File "mtrand.pyx", line 1417, in mtrand.RandomState.choice (numpy\random\mtrand\mtrand.c:15985)
ValueError: probabilities do not sum to 1

规范化:

>>> p = np.array(p)
>>> p /= p.sum()  # normalize
>>> np.random.choice([1,2,3,4,5,6,7,8,9, 10], 4, p=p, replace=False)
array([8, 4, 1, 6])

答案 1 :(得分:2)

将其转换为 float64:

p = np.asarray(p).astype('float64')
p = p / np.sum(p)
np.random.choice([1,2,3,4,5,6,7,8,9, 10], 4, p=p, replace=False)

这是受到另一篇文章的启发:How can I avoid value errors when using numpy.random.multinomial?

答案 2 :(得分:1)

看待差异的一种方法是:

numpy.set_printoptions(precision=15)
print(p)

这可能会告诉您4.17187500e-05实际上是4.17187500005e-05。请参阅the manual here

答案 3 :(得分:0)

ValueError:概率不等于1

这是一个已知的numpy错误。当numpy无法足够精确地处理浮点运算时,就会发生此错误。有时,概率总和约为0.9999999999997或1.0000000000003。他们会破坏np.random.choice()。

有一种解决方法:np.random.multinomial()。这种方法可以更精确地处理概率,而不必精确地是1.0。

pvals:浮点序列,长度为p每个p的概率 不同的结果。这些总和应为1(但是,最后一个元素 只要假设,只要 sum(pvals [:-1])<= 1)。

例如,我有一些选择,并且与这些选择相关联的normalized_weights。

np.random.multinomial()根据normalized_weights选择20次,并返回选择每个选择的次数。

choices = [......]
weights = np.array([......])
normalized_weights = weights / np.sum(weights)

number_of_choices = 20
resample_counts = np.random.multinomial(number_of_choices,
                                        normalized_weights)

chosen = []
resample_index = 0
for resample_count in resample_counts:
    for _ in range(resample_count):
        chosen.append(choices[resample_index])
    resample_index += 1