根据权重从列表中抽取可变长度元素
Variable length element sampling from list based on weights
我想 select 根据每个元素的给定权重从列表中选择一些项目。输出的长度未知。这需要做很多次。
所以,假设我有一个像 [[1, 0.2], [2, 0.3], [3, 0.45], [4, 0.05], [5,1.]]
这样的 [id, probability]
的列表,我想得到像 [[1,3,5], [5], [3,5], [5], [1,2,4,5], ...]
这样的东西
这是我的代码。它有效,但速度很慢(列表很长,[id, probability]
的 10,000 多个元素,我的结果是数千 selection
长)。你知道有什么方法可以让这个(多)更快吗?
import numpy as np
items = [[1, 0.2], [2, 0.3], [3, 0.45], [4, 0.05], [5,1.]]
combinations = []
for n in range(1000):
selection = []
for i in items:
chosen = np.random.choice([True, False], p=[i[1], 1.-i[1]])
if chosen:
selection.append(i[0])
combinations.append(selection)
您可以按如下方式矢量化采样步骤:
import numpy as np
# items = [[1, 0.2], [2, 0.3], [3, 0.45], [4, 0.05], [5,1.]]
items = [(i, np.random.rand()) for i in range(1000)]
def sample_original(itms, n=1000):
combinations = []
for n in range(n):
selection = []
for i in items:
chosen = np.random.choice([True, False], p=[i[1], 1.-i[1]])
if chosen:
selection.append(i[0])
combinations.append(selection)
def sample_numpy(itms, n=1000):
elts, probs = np.array(itms).T
m = len(elts)
return [elts[np.random.rand(m) < probs] for _ in range(n)]
主要观察结果是 np.random.rand(m) < probs
给出了 True/False
的随机向量,它以正确的概率选择原始列表中的元素。当有 1000 个项目时,这似乎快了 1000 倍:
%timeit sample_numpy(items)
%timeit sample_original(items)
10 loops, best of 3: 22.6 ms per loop
1 loop, best of 3: 21.9 s per loop
如果概率相对较高(结果选择并不稀疏),您可能希望将选择指示符存储在二维数组中以进一步提高性能。
我想 select 根据每个元素的给定权重从列表中选择一些项目。输出的长度未知。这需要做很多次。
所以,假设我有一个像 [[1, 0.2], [2, 0.3], [3, 0.45], [4, 0.05], [5,1.]]
这样的 [id, probability]
的列表,我想得到像 [[1,3,5], [5], [3,5], [5], [1,2,4,5], ...]
这是我的代码。它有效,但速度很慢(列表很长,[id, probability]
的 10,000 多个元素,我的结果是数千 selection
长)。你知道有什么方法可以让这个(多)更快吗?
import numpy as np
items = [[1, 0.2], [2, 0.3], [3, 0.45], [4, 0.05], [5,1.]]
combinations = []
for n in range(1000):
selection = []
for i in items:
chosen = np.random.choice([True, False], p=[i[1], 1.-i[1]])
if chosen:
selection.append(i[0])
combinations.append(selection)
您可以按如下方式矢量化采样步骤:
import numpy as np
# items = [[1, 0.2], [2, 0.3], [3, 0.45], [4, 0.05], [5,1.]]
items = [(i, np.random.rand()) for i in range(1000)]
def sample_original(itms, n=1000):
combinations = []
for n in range(n):
selection = []
for i in items:
chosen = np.random.choice([True, False], p=[i[1], 1.-i[1]])
if chosen:
selection.append(i[0])
combinations.append(selection)
def sample_numpy(itms, n=1000):
elts, probs = np.array(itms).T
m = len(elts)
return [elts[np.random.rand(m) < probs] for _ in range(n)]
主要观察结果是 np.random.rand(m) < probs
给出了 True/False
的随机向量,它以正确的概率选择原始列表中的元素。当有 1000 个项目时,这似乎快了 1000 倍:
%timeit sample_numpy(items)
%timeit sample_original(items)
10 loops, best of 3: 22.6 ms per loop
1 loop, best of 3: 21.9 s per loop
如果概率相对较高(结果选择并不稀疏),您可能希望将选择指示符存储在二维数组中以进一步提高性能。