簡體   English   中英

滑動窗口操作的Numpy Vectorization

[英]Numpy Vectorization of sliding-window operation

我有以下numpy數組:

arr_1 = [[1,2],[3,4],[5,6]]   # 3 X 2 
arr_2 = [[0.5,0.6],[0.7,0.8],[0.9,1.0],[1.1,1.2],[1.3,1.4]]  # 5 X 2

arr_1顯然是3 X 2陣列,而arr_25 X 2陣列。

現在沒有循環,我想以元素方式乘以arr_1和arr_2,以便我將滑動窗口技術(窗口大小3)應用於arr_2。

Example:

Multiplication 1:  np.multiply(arr_1,arr_2[:3,:])

Multiplication 2: np.multiply(arr_1,arr_2[1:4,:])

Multiplication 3: np.multiply(arr_1,arr_2[2:5,:])

我想以某種矩陣乘法形式做到這一點,使它比我目前的解決方案更快,形式如下:

for i in (2):
   np.multiply(arr_1,arr_2[i:i+3,:])  

因此,如果arr_2中的行數很大(數萬個數量級),那么這個解決方案並不能很好地擴展。

任何幫助將非常感激。

我們可以使用NumPy broadcasting以矢量化方式創建那些滑動窗口索引。 然后,我們可以簡單地將arr_2索引到那些用於創建3D數組並使用2D數組arr_1執行元素乘法的arr_1 ,這反過來將再次引入broadcasting

所以,我們會有一個像這樣的矢量化實現 -

W = arr_1.shape[0] # Window size
idx = np.arange(arr_2.shape[0]-W+1)[:,None] + np.arange(W)
out = arr_1*arr_2[idx]

運行時測試並驗證結果 -

In [143]: # Input arrays
     ...: arr_1 = np.random.rand(3,2)
     ...: arr_2 = np.random.rand(10000,2)
     ...: 
     ...: def org_app(arr_1,arr_2):
     ...:     W = arr_1.shape[0] # Window size
     ...:     L = arr_2.shape[0]-W+1
     ...:     out = np.empty((L,W,arr_1.shape[1]))
     ...:     for i in range(L):
     ...:        out[i] = np.multiply(arr_1,arr_2[i:i+W,:])
     ...:     return out
     ...: 
     ...: def vectorized_app(arr_1,arr_2):
     ...:     W = arr_1.shape[0] # Window size
     ...:     idx = np.arange(arr_2.shape[0]-W+1)[:,None] + np.arange(W)
     ...:     return arr_1*arr_2[idx]
     ...: 

In [144]: np.allclose(org_app(arr_1,arr_2),vectorized_app(arr_1,arr_2))
Out[144]: True

In [145]: %timeit org_app(arr_1,arr_2)
10 loops, best of 3: 47.3 ms per loop

In [146]: %timeit vectorized_app(arr_1,arr_2)
1000 loops, best of 3: 1.21 ms per loop

這是測試as_strided和Divakar廣播速度的一個很好的例子。

In [281]: %%timeit 
     ...: out=np.empty((L,W,arr1.shape[1]))
     ...: for i in range(L):
     ...:    out[i]=np.multiply(arr1,arr2[i:i+W,:])
     ...: 
10 loops, best of 3: 48.9 ms per loop
In [282]: %%timeit
     ...: idx=np.arange(L)[:,None]+np.arange(W)
     ...: out=arr1*arr2[idx]
     ...: 
100 loops, best of 3: 2.18 ms per loop
In [283]: %%timeit
     ...: arr3=as_strided(arr2, shape=(L,W,2), strides=(16,16,8))
     ...: out=arr1*arr3
     ...: 
1000 loops, best of 3: 805 µs per loop

創建Numpy數組而不枚舉數組,以便更多地比較這些方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM