numpy.random.choice
允许从向量中进行加权选择,即
arr = numpy.array([1, 2, 3])
weights = numpy.array([0.2, 0.5, 0.3])
choice = numpy.random.choice(arr, p=weights)
选择概率为0.2的1,概率为0.5的2和概率为0.3的3。
如果我们想对每个行都是概率向量的2D数组(矩阵)以向量化的方式快速进行操作,该怎么办?也就是说,我们想要一个来自随机矩阵的选择向量吗?这是超级慢的方式:
import numpy as np
m = 10
n = 100 # Or some very large number
items = np.arange(m)
prob_weights = np.random.rand(m, n)
prob_matrix = prob_weights / prob_weights.sum(axis=0, keepdims=True)
choices = np.zeros((n,))
# This is slow, because of the loop in Python
for i in range(n):
choices[i] = np.random.choice(items, p=prob_matrix[:,i])
print(choices)
:
array([ 4., 7., 8., 1., 0., 4., 3., 7., 1., 5., 7., 5., 3.,
1., 9., 1., 1., 5., 9., 8., 2., 3., 2., 6., 4., 3.,
8., 4., 1., 1., 4., 0., 1., 8., 5., 3., 9., 9., 6.,
5., 4., 8., 4., 2., 4., 0., 3., 1., 2., 5., 9., 3.,
9., 9., 7., 9., 3., 9., 4., 8., 8., 7., 6., 4., 6.,
7., 9., 5., 0., 6., 1., 3., 3., 2., 4., 7., 0., 6.,
3., 5., 8., 0., 8., 3., 4., 5., 2., 2., 1., 1., 9.,
9., 4., 3., 3., 2., 8., 0., 6., 1.])
这篇文章表明,cumsum
并且bisect
可能是一种潜在的方法,而且很快。但是虽然numpy.cumsum(arr, axis=1)
可以沿numpy数组的一个轴执行此操作,但是该bisect.bisect
函数一次只能在单个数组上运行。同样,也numpy.searchsorted
仅适用于一维阵列。
是否有一种仅使用矢量化操作来完成此操作的快速方法?
这是一个非常快速的完全矢量化版本:
def vectorized(prob_matrix, items):
s = prob_matrix.cumsum(axis=0)
r = np.random.rand(prob_matrix.shape[1])
k = (s < r).sum(axis=0)
return items[k]
从理论上讲 ,searchsorted
是用于在累积求和的概率中查找随机值的正确函数,但m
由于相对较小,因此k = (s < r).sum(axis=0)
最终速度要快得多。它的时间复杂度为O(m),而searchsorted
方法为O(log(m)),但这仅对大得多才有意义m
。
另外
,cumsum
也是O(m),所以vectorized
和@perimosocordiaeimproved
都是O(m)。(m
实际上,如果您的计算机更大,则必须运行一些测试以查看m
此方法变慢之前可以达到的大小。)
这是我使用m = 10
和n = 10000
(使用函数original
和improved
@perimosocordiae的答案)得到的时间:
In [115]: %timeit original(prob_matrix, items)
1 loops, best of 3: 270 ms per loop
In [116]: %timeit improved(prob_matrix, items)
10 loops, best of 3: 24.9 ms per loop
In [117]: %timeit vectorized(prob_matrix, items)
1000 loops, best of 3: 1 ms per loop
定义功能的完整脚本为:
import numpy as np
def improved(prob_matrix, items):
# transpose here for better data locality later
cdf = np.cumsum(prob_matrix.T, axis=1)
# random numbers are expensive, so we'll get all of them at once
ridx = np.random.random(size=n)
# the one loop we can't avoid, made as simple as possible
idx = np.zeros(n, dtype=int)
for i, r in enumerate(ridx):
idx[i] = np.searchsorted(cdf[i], r)
# fancy indexing all at once is faster than indexing in a loop
return items[idx]
def original(prob_matrix, items):
choices = np.zeros((n,))
# This is slow, because of the loop in Python
for i in range(n):
choices[i] = np.random.choice(items, p=prob_matrix[:,i])
return choices
def vectorized(prob_matrix, items):
s = prob_matrix.cumsum(axis=0)
r = np.random.rand(prob_matrix.shape[1])
k = (s < r).sum(axis=0)
return items[k]
m = 10
n = 10000 # Or some very large number
items = np.arange(m)
prob_weights = np.random.rand(m, n)
prob_matrix = prob_weights / prob_weights.sum(axis=0, keepdims=True)
问题内容: 我想从集合中选择一个随机项目,但是选择任何项目的机会应与相关的权重成比例 输入示例: 因此,如果我有4种可能的物品,那么没有重量的任何一件物品的机会将是四分之一。 在这种情况下,用户遭受痛苦之剑的可能性应该是三刃剑的十倍。 如何在Java中进行加权随机选择? 问题答案: Apache Commons中现在有一个用于此的类: 这里是,像(假设Item接口阿恩的答案): 或在Java 8中
假设我得到的是范围内的随机数,使用: 假设它给出的数字小于或等于25,你就赢了,如果它给出的数字大于25,我就赢了。然后我有75%的机会赢。 我该如何加权这个数字大于25的概率的某个百分比,比如说1%。 所以,基本上,我试图将我获胜的几率再提高1%,而不是仅仅说“你赢24分或更少” 如果不清楚,请告诉我。
问题内容: 从大型mysql表中选择随机行的快速方法是什么? 我正在使用php,但是我对任何解决方案都感兴趣,即使它是另一种语言也是如此。 问题答案: 获取所有ID,从中随机选择一个ID,然后检索整行。 如果您知道ID是连续无孔的,则只需获取最大值并计算一个随机ID。 如果到处都有孔,但大多数是顺序值,并且您不关心随机偏斜,则获取最大值,计算一个id,然后选择ID等于或大于您所计算的ID的第一行。
问题内容: 我有一个大于1000万行的巨大表。我需要从中有效地获取5000个随机样本。我有一些限制因素,使我想要的总行数减少到9密耳。 我尝试通过NEWID()使用order,但是该查询将花费很长时间,因为它必须对所有行进行表扫描。 有没有更快的方法可以做到这一点? 问题答案: 如果您可以使用伪随机抽样并且您使用的是SQL Server 2005/2008,则请看一下TABLESAMPLE。例如,
假设我有一个随机选择的项目池。 我使用一个简单的加权选择算法来做到这一点: 计算项目权重总和 在0和权重和之间选择一个随机数 迭代项目,并按项目权重减少,选择项目时 同时,约束传播算法更新可用项目池。 例如,假设我们有一个N乘N的网格,每个单元格可以选择一个数字 使用上述算法,通过加权选择完成选择 一旦一个单元选择了它的编号,它还会使用一些规则限制相邻单元的可用编号 我的问题是: 假设牢房A和B是
问题内容: 如何最好地编写一个查询,从总共60万行中随机选择10行? 问题答案: 一个出色的职位,可以处理多种情况,从简单到有缺口,再到有缺口的不均匀。 http://jan.kneschke.de/projects/mysql/order-by- rand/ 对于大多数一般情况,这是您的操作方法: 这假定id的分布是相等的,并且id列表中可能存在间隙。请参阅文章以获取更多高级示例