2013-04-10 47 views
4

我执行一些计算来获取numpy数组列表。随后,我想找到沿第一轴的最大值。我目前的实施(见下文)非常缓慢,我想找到替代方案。当应用于数组列表时,Numpy最大速度很慢

原始

pending = [<list of items>] 
matrix = [compute(item) for item in pending if <some condition on item>] 
dominant = np.max(matrix, axis = 0) 

修订1:此实现更快的(〜10倍;这大概是因为numpy的并不需要弄清楚阵列的形状)

pending = [<list of items>] 
matrix = [compute(item) for item in pending if <some condition on item>] 
matrix = np.vstack(matrix) 
dominant = np.max(matrix, axis = 0) 

我经历了几次测试,并且放缓似乎是由于将阵列列表内部转换为一个numpy数组所致

Timer unit: 1e-06 s 
Total time: 1.21389 s 
Line # Hits   Time Per Hit % Time Line Contents 
============================================================== 
4           def direct_max(list_of_arrays): 
5  1000  1213886 1213.9 100.0  np.max(list_of_arrays, axis = 0) 

Total time: 1.20766 s 
Line # Hits   Time Per Hit % Time Line Contents 
============================================================== 
8           def numpy_max(list_of_arrays): 
9  1000  1151281 1151.3  95.3  list_of_arrays = np.array(list_of_arrays) 
10  1000  56384  56.4  4.7  np.max(list_of_arrays, axis = 0) 

Total time: 0.15437 s 
Line # Hits   Time Per Hit % Time Line Contents 
============================================================== 
12           @profile 
13           def stack_max(list_of_arrays): 
14  1000  102205 102.2  66.2  list_of_arrays = np.vstack(list_of_arrays) 
15  1000  52165  52.2  33.8  np.max(list_of_arrays, axis = 0) 

有没有什么办法来加速最大函数,或者是否有可能用我的计算结果高效地填充一个numpy数组,以便max最快?

+0

什么数据类型是'items'? – mgilson 2013-04-10 18:00:56

+11

最快的方法是首先用2d numpy数组而不是数组列表来启动。如果列表的长度不同,只需使用-inf或nan即可。 – Bitwise 2013-04-10 18:16:45

+0

@mgilson:项目本身是表单的键值对(键:一些可散列类型,值:numpy数组) – 2013-04-10 18:19:56

回答

3

您可以使用reduce(np.maximum, matrix),这里是一个测试:

import numpy as np 
np.random.seed(0) 

N, M = 1000, 1000 
matrix = [np.random.rand(N) for _ in xrange(M)] 

%timeit np.max(matrix, axis = 0) 
%timeit np.max(np.vstack(matrix), axis = 0) 
%timeit reduce(np.maximum, matrix) 

结果是:

10 loops, best of 3: 116 ms per loop 
10 loops, best of 3: 10.6 ms per loop 
100 loops, best of 3: 3.66 ms per loop 

编辑

'argmax()”是比较困难的,但你可以使用for循环:

def argmax_list(matrix): 
    m = matrix[0].copy() 
    idx = np.zeros(len(m), dtype=np.int) 
    for i, a in enumerate(matrix[1:], 1): 
     mask = m < a 
     m[mask] = a[mask] 
     idx[mask] = i 
    return idx 

它仍然快于argmax()

%timeit np.argmax(matrix, axis=0) 
%timeit np.argmax(np.vstack(matrix), axis=0) 
%timeit argmax_list(matrix) 

结果:

10 loops, best of 3: 131 ms per loop 
10 loops, best of 3: 21 ms per loop 
100 loops, best of 3: 13.1 ms per loop 
+0

这太好了,还有一个问题:你有建议如何使用相同的方法来模拟'np.argmax'的行为吗? – 2013-04-11 12:50:04