How to matrix multiply each column from two matrices in numpy?

75 views Asked by At

I have two matrices,

A = np.array([[1, 3, 5],
             [2, 4, 6]])
b = np.array([[7, 9, 11],
             [8, 10, 12]])
 

The operation I want to perform is multiplying

# Column 1
A_1 = np.matmul([[1],[2]], [[7, 8]])
# [1]
# [2] * [7, 8] = [7, 8]
#                 [14, 16]

# Column 2
A_2 = np.matmul([[3],[4]], [[9, 10]])
# [3]
# [4] * [9, 10] = [27, 30]
#                 [36, 40]

# A_1+A_2 = [34 38
#           50 56]


....
# Column N

For each column then sum up the resulting matrices. My matrices will always have a shape of (2, N). In words, multiply i'th column of matrix A with the transpose of the i'th column of matrix B then sum up each 2x2 matrix from each column pair.

I know I can probably loop over each entry and calculate it this way but I don't think thats the spirit of numpy and think there has to be a better way.

3

There are 3 answers

7
Andrej Kesely On

IIUC you can do this with np.einsum:

A = np.array([[1, 3, 5], [2, 4, 6]])
B = np.array([[7, 9, 11], [8, 10, 12]])

out = np.einsum("ij,kj->ik", A, B)
print(out)

Prints:

[[ 89  98]
 [116 128]]

EDIT: As @NickODell stated, if you want to sum the 2x2 matrices to one number on each column you can use:

out = np.einsum("ij,kj->j", A, B)
print(out)

Prints:

[ 45 133 253]
3
Julien On

Well isn't this just A @ b.T?

0
hpaulj On
In [62]: A = np.array([[1, 3, 5],
    ...:              [2, 4, 6]])
    ...: b = np.array([[7, 9, 11],
    ...:              [8, 10, 12]])

The suggested answers, with some confusion:

In [63]: [email protected]
Out[63]: 
array([[ 89,  98],
       [116, 128]])

In [64]: np.einsum('ij,kj->ik',A,b)
Out[64]: 
array([[ 89,  98],
       [116, 128]])

In [65]: np.einsum('ij,kj->j',A,b)
Out[65]: array([ 45, 133, 253])

Your partial calculation:

In [70]: [A[:,[i]]*b[:,[i]].T for i in range(3)]
Out[70]: 
[array([[ 7,  8],
        [14, 16]]),
 array([[27, 30],
        [36, 40]]),
 array([[55, 60],
        [66, 72]])]

summing 2 of those:

In [72]: sum([A[:,[i]]*b[:,[i]].T for i in range(2)])
Out[72]: 
array([[34, 38],
       [50, 56]])

Summing all 3:

In [73]: sum([A[:,[i]]*b[:,[i]].T for i in range(3)])
Out[73]: 
array([[ 89,  98],
       [116, 128]])

But wait, where have I seen those numbers before?

Since these are both 2d arrays, we can use the old-school np.dot

In [74]: np.dot(A,b.T)
Out[74]: 
array([[ 89,  98],
       [116, 128]])

Hopefully this shows why a clear, worked out example, even if written in loops is desirable.