Home > OS >  Multiply a 3D array with a 2D array
Multiply a 3D array with a 2D array

Time:03-23

I have a 3D numpy array and I want to multiply it with a 2D array, The 3D looks like follows:

C= np.zeros((3, 2, 2))
C[0][0] = [0,0]
C[0][1] = [0,1]
C[1][0] = [1,0]
C[1][1] = [1,1]
C[2][0] = [1,2]
C[2][1] = [2,1]

The 2D array looks like:

V = np.zeros((3,2)) 
V[0][0] = 1
V[0][1] = 2
V[1][0] = 1
V[1][1] = 3
V[2][0] = 4 
V[2][1] = 5

The result R is to be a 2X2 2D array(4 elements in total) R=[[5,8],[13,10]] where:

R[0] = V[0][0]*C[0][0] V[1][0]*C[1][0] V[2][0]*C[2][0] = [5,8] (first row of R)

R[1] = V[0][1]*C[0][1] V[1][1]*C[1][1] V[2][1]*C[2][1] = [13,10] (second row of R)

This is just an example, How Can I get R using numpy matrix multiplication operation with V and C (with no for loop!). Please help!

Sorry I made some edit later, the comment showed an old example, it should be good now

CodePudding user response:

Your example is confusing. Why do you say your expected result is [[1, 0], [5, 10]] but in your example you also say R should be [[5, 8], [13, 10]]?

I hope this was just a typo on your part because it's not clear from your example how you'd get from one to the other.

In any case:

(V.T * C.T).sum(axis=2).T

Output:

array([[ 5.,  8.],
       [13., 10.]])

CodePudding user response:

In [20]: C          # (3,2,2)
Out[20]: 
array([[[0, 0],
        [0, 1]],

       [[1, 0],
        [1, 1]],

       [[1, 2],
        [2, 1]]])
In [21]: V         # (3,2)
Out[21]: 
array([[1., 2.],
       [1., 3.],
       [4., 5.]])

Expand V to (3,2,1). This broadcasts with C to produce a (3,2,2):

In [22]: C * V[:,:,None]
Out[22]: 
array([[[ 0.,  0.],
        [ 0.,  2.]],

       [[ 1.,  0.],
        [ 3.,  3.]],

       [[ 4.,  8.],
        [10.,  5.]]])

and sum on the first axis to make (2,2) result:

In [23]: (C * V[:,:,None]).sum(axis=0)
Out[23]: 
array([[ 5.,  8.],
       [13., 10.]])

This answer cleans up @ddjohns answer; he did the hard work.

The sum-of-products can be expressed with einsum as:

In [24]: np.einsum('ijk,ij->jk',C,V)
Out[24]: 
array([[ 5.,  8.],
       [13., 10.]])

Reordering the axes, we can express it as a more conventional sum-of-products:

In [25]: np.einsum('jki,ji->jk',C.transpose(1,2,0),V.transpose(1,0))
Out[25]: 
array([[ 5.,  8.],
       [13., 10.]])

And use that to cast it as a matmul:

In [28]: (C.transpose(1,2,0)@V.transpose(1,0)[:,:,None]).squeeze(2)
Out[28]: 
array([[ 5.,  8.],
       [13., 10.]])

[28] is probably fastest, but [23] may be easier to understand.

  • Related