使用 SciPy/NumPy 循环有限概率权重
Loop over finite probability weights with SciPy/NumPy
让我们有一个单一的事件概率 prob
,它是一个介于 0-1 之间的标量。如果我想以 0.1 的增量遍历所有可能的概率,那么我可以使用:
prob = np.arange(0.01, 1, 0.1)
现在假设我有 5 个事件(独立的,概率总和为 1),每个事件的概率为 p_i
。我想要多维概率数组,例如:
1.0 - 0.0 - 0.0 - 0.0 - 0.0
0.9 - 0.1 - 0.0 - 0.0 - 0.0
0.9 - 0.0 - 0.1 - 0.0 - 0.0
0.9 - 0.0 - 0.0 - 0.1 - 0.0
0.9 - 0.0 - 0.0 - 0.0 - 0.1
0.8 - 0.1 - 0.1 - 0.0 - 0.0
0.8 - 0.1 - 0.0 - 0.1 - 0.0
. . . . .
. . . . .
. . . . .
0.2 - 0.2 - 0.2 - 0.2 - 0.2
有没有比考虑 0 - 0.1 - ... - 1 的所有组合并删除总和不为 1 的行更聪明的方法?如果是,最简单的方法是什么?
可能有一个使用 itertools 的更优雅的解决方案,但这可能没问题并且不使用依赖项?:
for i in prob:
for j in prob:
for k in prob:
for l in prob:
m = 1 - i - j - l
if m>=0:
print(i,j,k,l,m)
您可以使用 itertools.product
和 filter
创建所有总和为 10 的组合并将其传递给数组:
import itertools
f = filter(lambda x: sum(x) == 10, itertools.product(*[range(11)]*5))
x = np.array(list(f)).astype(np.float)/10
x
>> array([[0. , 0. , 0. , 0. , 1. ],
[0. , 0. , 0. , 0.1, 0.9],
[0. , 0. , 0. , 0.2, 0.8],
...,
[0.9, 0. , 0.1, 0. , 0. ],
[0.9, 0.1, 0. , 0. , 0. ],
[1. , 0. , 0. , 0. , 0. ]])
编辑
郑重声明,这是一种不使用过滤的更有效的方法。本质上,您创建 k
个箱子(在您的示例中为 10),并将它们 "assign" 以所有可能的组合创建 "n" 个样本(在您的示例中为 3),使用 combinations_with_replacement
然后,您计算每个样本获得多少个 bin:这是您的概率。这种方法理解起来比较复杂,但避免了filter
,因此效率更高。你可以试试 0.01 (k = 100
)
n = 3 # number of samples
k = 100 # number of subdivisions
f = itertools.combinations_with_replacement(range(3),k) #your iterator
r = np.array(list(f)) #your array of combinations
x = np.vstack((r==i).sum(1) for i in range(n)).T/k #your probability matrix
让我们有一个单一的事件概率 prob
,它是一个介于 0-1 之间的标量。如果我想以 0.1 的增量遍历所有可能的概率,那么我可以使用:
prob = np.arange(0.01, 1, 0.1)
现在假设我有 5 个事件(独立的,概率总和为 1),每个事件的概率为 p_i
。我想要多维概率数组,例如:
1.0 - 0.0 - 0.0 - 0.0 - 0.0
0.9 - 0.1 - 0.0 - 0.0 - 0.0
0.9 - 0.0 - 0.1 - 0.0 - 0.0
0.9 - 0.0 - 0.0 - 0.1 - 0.0
0.9 - 0.0 - 0.0 - 0.0 - 0.1
0.8 - 0.1 - 0.1 - 0.0 - 0.0
0.8 - 0.1 - 0.0 - 0.1 - 0.0
. . . . .
. . . . .
. . . . .
0.2 - 0.2 - 0.2 - 0.2 - 0.2
有没有比考虑 0 - 0.1 - ... - 1 的所有组合并删除总和不为 1 的行更聪明的方法?如果是,最简单的方法是什么?
可能有一个使用 itertools 的更优雅的解决方案,但这可能没问题并且不使用依赖项?:
for i in prob:
for j in prob:
for k in prob:
for l in prob:
m = 1 - i - j - l
if m>=0:
print(i,j,k,l,m)
您可以使用 itertools.product
和 filter
创建所有总和为 10 的组合并将其传递给数组:
import itertools
f = filter(lambda x: sum(x) == 10, itertools.product(*[range(11)]*5))
x = np.array(list(f)).astype(np.float)/10
x
>> array([[0. , 0. , 0. , 0. , 1. ],
[0. , 0. , 0. , 0.1, 0.9],
[0. , 0. , 0. , 0.2, 0.8],
...,
[0.9, 0. , 0.1, 0. , 0. ],
[0.9, 0.1, 0. , 0. , 0. ],
[1. , 0. , 0. , 0. , 0. ]])
编辑
郑重声明,这是一种不使用过滤的更有效的方法。本质上,您创建 k
个箱子(在您的示例中为 10),并将它们 "assign" 以所有可能的组合创建 "n" 个样本(在您的示例中为 3),使用 combinations_with_replacement
然后,您计算每个样本获得多少个 bin:这是您的概率。这种方法理解起来比较复杂,但避免了filter
,因此效率更高。你可以试试 0.01 (k = 100
)
n = 3 # number of samples
k = 100 # number of subdivisions
f = itertools.combinations_with_replacement(range(3),k) #your iterator
r = np.array(list(f)) #your array of combinations
x = np.vstack((r==i).sum(1) for i in range(n)).T/k #your probability matrix