简体   繁体   中英

NumPy dot product: take product of vector products (rather than sum)

Say i have two matrices: M is 2x3, and C is 3x4...

import numpy as np
M = np.matrix([ [1,2,3], [4,5,6]])
C = np.matrix([ [1,1,2,2], [1,2,1,2], [2,1,1,1]])

I need to multiply these matrices to get a result of size 2x4. This would be easy with np.dot(M, C) , but i want to multiply the vector products rather than sum them.

For example, a regular dot product would do:

result[0,0] = (M[0,0]*C[0,0]) + (M[0,1]*C[1,0]) + (M[0,2]*C[2,0])
# result[0,0] = (1*1) + (2*1) + (3*2)
# result[0,0] = 9

I simply want to replace the plus signs with multiplication signs...

result[0,0] = (M[0,0]*C[0,0]) * (M[0,1]*C[1,0]) * (M[0,2]*C[2,0])
# result[0,0] = (1*1) * (2*1) * (3*2)
# result[0,0] = 12

My best solution has relied on looping over rows of M --

result = np.empty( (2,4) )
for i in range(2):
    result[i,:] = np.prod(np.multiply(np.tile(M[i,:].T , (1,4)), C) , axis=0)

Breaking that down, each row of M is transposed, then tiled (using np.tile ) so it is the same size as C (ie, 3x4). Then i multiply the matrices element-wise, and take the product of each column.

In the actual program i'm writing, M and C are not necessarily integer, can be of any size, and this calculation is carried out many thousands of times. I'm wondering if anyone knows of a way to do this that is quick and readable.

UPDATE

@Warren Weckesser offered a great solution. But now i have a new challenge--specifically, what if i wanted to subtract a number from the vector products prior to multiplying them?

This can be done like so in my earlier solution:

result1 = np.empty( (2,4) ) 
for i in range(2): 
    result1[i,:] = np.prod( 1 - np.multiply( np.tile(M[i,:].T , (1,4)), C) , axis=0)

I have played around with the solution provided by @Warren Weckesser, to no avail. I would absolutely love to figure out something more elegant!

Here's a quick way:

In [68]: M
Out[68]: 
matrix([[1, 2, 3],
        [4, 5, 6]])

In [69]: C
Out[69]: 
matrix([[1, 1, 2, 2],
        [1, 2, 1, 2],
        [2, 1, 1, 1]])

In [70]: M.prod(axis=1) * C.prod(axis=0)
Out[70]: 
matrix([[ 12,  12,  12,  24],
        [240, 240, 240, 480]])

M.prod(axis=1) is the product of the elements in the rows of M . Because M is a matrix instance, the shape of the result is (2, 1):

In [71]: M.prod(axis=1)
Out[71]: 
matrix([[  6],
        [120]])

Similarly, C.prod(axis=0) is the product down the columns of C :

In [72]: C.prod(axis=0)
Out[72]: matrix([[2, 2, 2, 4]])

Then the matrix product of these two matrices, with shape (2, 1) and (1, 4), has shape (2, 4), and it contains the products that you want.

With arrays, use the keepdims argument of prod() to maintain the 2D shapes, and use the dot() method instead of * :

In [79]: m = M.A

In [80]: c = C.A

In [81]: m
Out[81]: 
array([[1, 2, 3],
       [4, 5, 6]])

In [82]: c
Out[82]: 
array([[1, 1, 2, 2],
       [1, 2, 1, 2],
       [2, 1, 1, 1]])

In [83]: m.prod(axis=1, keepdims=True).dot(c.prod(axis=0, keepdims=True))
Out[83]: 
array([[ 12,  12,  12,  24],
       [240, 240, 240, 480]])

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM