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.