Numpy Vectorización de la operación de ventana deslizante

Tengo los siguientes arreglos 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 es claramente una matriz de 3 X 2 , mientras que arr_2 es una matriz de 5 X 2 .

Ahora, sin hacer un bucle, quiero multiplicar arr_1 y arr_2 de manera inteligente, de modo que aplique una técnica de ventana deslizante (tamaño de ventana 3) a 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,:]) 

Quiero hacer esto en una especie de forma de multiplicación de matrices para que sea más rápida que mi solución actual, que es de la forma:

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

Entonces, si el número de filas en arr_2 es ​​grande (del orden de decenas de miles), esta solución realmente no se escala muy bien.

Cualquier ayuda sería muy apreciada.

Podemos usar NumPy broadcasting para crear esos índices de ventana deslizante de manera vectorial. Luego, podemos simplemente indexar en arr_2 con aquellos para crear una matriz 3D y realizar una multiplicación de elementos con 2D matriz 2D arr_1 , que a su vez provocará la broadcasting nuevamente.

Entonces, tendríamos una implementación vectorizada como tal –

 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] 

Runtime prueba y verifica resultados –

 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 

Este es un buen caso para probar la velocidad de las transmisiones por as_strided y de 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 

Cree una matriz de Numpy sin enumerar la matriz para obtener más de una comparación de estos métodos.