2016-03-15 100 views
3

我有一个numpy的操作,我称之为集中,我需要优化:聚合numpy的功能

np.sum(a**2, axis=1)**.5 # where a is a 2 dimensional ndarray 

这一操作是由三个功能,需要通过“A”三次迭代。将一个功能下的所有操作聚合在一起并沿轴1使用该功能会更有效率。不幸的是,numpy的apply_along_axis功能不是一种选择,因为性能在x1000左右更差。

有没有聚合几个numpy操作的方法,所以它只需要在数组上循环一次?

回答

4

当浮点阵列时,您可以使用np.einsum -

np.sqrt(np.einsum('ij,ij->i',a,a)) 

运行测试 -

In [34]: a = np.random.rand(1000,1000) 

In [35]: np.allclose(np.sum(a**2, axis=1)**.5,np.sqrt(np.einsum('ij,ij->i',a,a))) 
Out[35]: True 

In [36]: %timeit np.sum(a**2, axis=1)**.5 
100 loops, best of 3: 7.57 ms per loop 

In [37]: %timeit np.sqrt(np.einsum('ij,ij->i',a,a)) 
1000 loops, best of 3: 1.52 ms per loop 
+0

谢谢。这比我预期的还要好! – MonkeyButter

+0

@MonkeyButter很高兴帮助! 'np.einsum'是纯粹的魔法! :) – Divakar

3

看看numexpr,它可以让你更快的计算数值表达式比纯numpy

In [19]: a = np.arange(1e6).reshape(1000,1000) 

In [20]: import numexpr as ne 

In [21]: %timeit np.sum(a**2,axis=1)**0.5 
100 loops, best of 3: 6.08 ms per loop 

In [22]: %timeit ne.evaluate("sum(a**2,axis=1)")**0.5 
100 loops, best of 3: 4.27 ms per loop 

**0.5不是表达式的一部分,因为sum是还原操作,需要计算的最后在表达式中。您还可以对sqrt/**0.5运行另一项评估。

+0

'numexpr'为'sqrt'过,所以也许可以帮助更换' ** 0.5'?尽管这可能意味着嵌套两个“评估”电话。 – Divakar

+0

'sqrt'只花了'sum'的大约1%的时间,所以我认为这是一点不必要的优化。 –