2016-03-15 72 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%的時間,所以我認爲這是一點不必要的優化。 –