Producto de computación de la fila i de array1 y la columna iith de array2 – NumPy

Tengo una matriz M1 de forma (N*2) y otra matriz M2 (2*N) , quiero obtener un resultado de (N) , cada elemento i es el producto de la fila i de M1 y la columna i de M2 . Intenté usar el punto en NumPy, pero solo me puede dar el resultado de la multiplicación de la matriz, que es (N*N) , por supuesto, puedo tomar la diagonal que es lo que quiero, me gustaría saber si hay una mejor manera de hacer esto?

Enfoque # 1

Puedes usar np.einsum

 np.einsum('ij,ji->i',M1,M2) 

Explicación:

La solución original se vería así:

 def original_app(M1,M2): N = M1.shape[0] out = np.zeros(N) for i in range(N): out[i] = M1[i].dot(M2[:,i]) return out 

Así, para cada iteración, tenemos:

 out[i] = M1[i].dot(M2[:,i]) 

Mirando el iterador, necesitamos alinear el primer eje de M1 con el segundo eje de M2 . Nuevamente, ya que estamos realizando matrix-multiplication y eso, por su misma definición, está alineando el segundo eje de M1 con el primer eje de M2 y también reduciendo la sum de estos elementos en cada iteración.

Cuando se traslada a einsum , mantenga los ejes alineados entre las dos entradas para que tengan la misma cadena al especificar la notación de cadena. Entonces, las entradas serían 'ij,ji para M1 y M2 respectivamente. La salida después de perder la segunda cadena de M1 , que es igual a la primera cadena de M2 en esa reducción de sum, debe dejarse como i . Por lo tanto, la notación de cadena completa sería: 'ij,ji->i' y la solución final como: np.einsum('ij,ji->i',M1,M2) .

Enfoque # 2

El número de columnas en M1 o el número de filas en M2 es 2 . Así que, alternativamente, podemos simplemente dividir, realizar la multiplicación de elementos y resumirlos, como así:

 M1[:,0]*M2[0] + M1[:,1]*M2[1] 

Prueba de tiempo de ejecución

 In [431]: # Setup inputs ...: N = 1000 ...: M1 = np.random.rand(N,2) ...: M2 = np.random.rand(2,N) ...: In [432]: np.allclose(original_app(M1,M2),np.einsum('ij,ji->i',M1,M2)) Out[432]: True In [433]: np.allclose(original_app(M1,M2),M1[:,0]*M2[0] + M1[:,1]*M2[1]) Out[433]: True In [434]: %timeit original_app(M1,M2) 100 loops, best of 3: 2.09 ms per loop In [435]: %timeit np.einsum('ij,ji->i',M1,M2) 100000 loops, best of 3: 13 µs per loop In [436]: %timeit M1[:,0]*M2[0] + M1[:,1]*M2[1] 100000 loops, best of 3: 14.2 µs per loop 

¡Aceleración masiva allí!