使用NumPy多次对大型数组进行采样的有效方法?

Ano*_*ous 7 python statistics optimization numpy list-comprehension

如果您不关心我正在尝试实施的细节,只需跳过较低的水平线

我正在尝试使用NumPy对某些统计信息进行自举错误估计.我有一个数组x,并希望计算f(x)错误分析中常见的高斯假设不成立的统计量的误差.x非常大.

为此,我x使用重新采样numpy.random.choice(),其中我的重新采样的大小是原始数组的大小,替换:

resample = np.random.choice(x, size=len(x), replace=True)

这让我有了新的认识x.此操作现在必须重复约1,000次,以提供准确的误差估计.如果我生成这种性质的1,000个重新采样;

resamples = [np.random.choice(x, size=len(x), replace=True) for i in range(1000)]

然后计算f(x)每个实现的统计量;

results = [f(arr) for arr in resamples]

然后我推断出f(x)类似的错误

np.std(results)

这个想法是,尽管使用高斯误差分析无法描述f(x) 自身,但是f(x)受随机误差影响的措施的分布可以是.


好的,这是一个引导程序.现在,我的问题是那条线

resamples = [np.random.choice(x, size=len(x), replace=True) for i in range(1000)]

对于大型阵列来说非常慢.没有列表理解,有更聪明的方法吗?第二个清单理解

results = [f(arr) for arr in resamples]

也可能很慢,具体取决于功能的细节f(x).

Div*_*kar 8

由于我们允许重复,因此我们可以一次性生成所有索引np.random.randint,然后简单地使索引resamples等效即可,就像这样-

num_samples = 1000
idx = np.random.randint(0,len(x),size=(num_samples,len(x)))
resamples_arr = x[idx]
Run Code Online (Sandbox Code Playgroud)

另一种方法是从均匀分布生成随机数,numpy.random.rand并按比例缩放到数组的长度,如下所示:

resamples_arr = x[(np.random.rand(num_samples,len(x))*len(x)).astype(int)]
Run Code Online (Sandbox Code Playgroud)

与运行测试x5000elems的-

In [221]: x = np.random.randint(0,10000,(5000))

# Original soln
In [222]: %timeit [np.random.choice(x, size=len(x), replace=True) for i in range(1000)]
10 loops, best of 3: 84 ms per loop

# Proposed soln-1
In [223]: %timeit x[np.random.randint(0,len(x),size=(1000,len(x)))]
10 loops, best of 3: 76.2 ms per loop

# Proposed soln-2
In [224]: %timeit x[(np.random.rand(1000,len(x))*len(x)).astype(int)]
10 loops, best of 3: 59.7 ms per loop
Run Code Online (Sandbox Code Playgroud)

对于很大 x

有了一个非常大的数组x600,000元素,你可能不希望所有为那些指数1000样本。在这种情况下,每个样本解决方案的时间安排如下:

In [234]: x = np.random.randint(0,10000,(600000))

# Original soln
In [235]: %timeit np.random.choice(x, size=len(x), replace=True)
100 loops, best of 3: 13 ms per loop

# Proposed soln-1
In [238]: %timeit x[np.random.randint(0,len(x),len(x))]
100 loops, best of 3: 12.5 ms per loop

# Proposed soln-2
In [239]: %timeit x[(np.random.rand(len(x))*len(x)).astype(int)]
100 loops, best of 3: 9.81 ms per loop
Run Code Online (Sandbox Code Playgroud)