Numpy dot product between a 3d matrix and 2d matrix

Question:

I have a 3d array that has shape (2, 10, 3) and a 2d array that has shape (2, 3) like this:

print(t) #2d array

Output:

[[1.003   2.32    3.11   ]
 [1.214   5.32    2.13241]]

print(normal) #3d array

Output:

[[[0.69908573 0.0826756  0.84485978]
  [0.51058213 0.4052637  0.5068118 ]
  [0.45974276 0.25819549 0.10780089]
  [0.27484999 0.33367648 0.128262  ]
  [0.35963389 0.77600065 0.89393939]
  [0.46937506 0.59291623 0.06620307]
  [0.87603987 0.44414505 0.83394174]
  [0.83186093 0.62491876 0.38160734]
  [0.96819897 0.80183442 0.75102768]
  [0.54182908 0.19403844 0.07925769]]

 [[2.82248573 3.2341756  0.96825978]
  [2.63398213 3.5567637  0.6302118 ]
  [2.58314276 3.40969549 0.23120089]
  [2.39824999 3.48517648 0.251662  ]
  [2.48303389 3.92750065 1.01733939]
  [2.59277506 3.74441623 0.18960307]
  [2.99943987 3.59564505 0.95734174]
  [2.95526093 3.77641876 0.50500734]
  [3.09159897 3.95333442 0.87442768]
  [2.66522908 3.34553844 0.20265769]]]

How can I get each row in the 2d array t to get the corresponding dot product in the 3d array normal such that the array I end up with a shape (2, 10) where each contains all 10 dot products between the nth row in 2d array and nth matrix in 3d array?

[0.62096458 0.62618459 0.37528887 0.5728386  1.19634398 0.79620507
 1.997884   0.75229492 1.2236496  0.4210626 ]
[2.96347746 3.30738892 3.50596579 4.93082295 5.33811805 4.44872493
 7.33480393 4.19173472 4.7406248  7.83229689]
Asked By: Aayush Lakhotia

||

Answers:

You can use numpy.einsum (np.einsum('ijk,ik->ij', t, normal)) to get this result:

import numpy as np

normal = np.array([
    [1.003,2.32,3.11],
    [1.214,5.32,2.13241]
])


t = np.array([
    [ 
        [0.69908573, 0.0826756,  0.84485978],
        [0.51058213, 0.4052637,  0.5068118 ],
        [0.45974276, 0.25819549, 0.10780089],
        [0.27484999, 0.33367648, 0.128262  ],
        [0.35963389, 0.77600065, 0.89393939],
        [0.46937506, 0.59291623, 0.06620307],
        [0.87603987, 0.44414505, 0.83394174],
        [0.83186093, 0.62491876, 0.38160734],
        [0.96819897, 0.80183442, 0.75102768],
        [0.54182908, 0.19403844, 0.07925769]
    ],

    [
        [2.82248573, 3.2341756,  0.96825978],
        [2.63398213, 3.5567637,  0.6302118 ],
        [2.58314276, 3.40969549, 0.23120089],
        [2.39824999, 3.48517648, 0.251662  ],
        [2.48303389, 3.92750065, 1.01733939],
        [2.59277506, 3.74441623, 0.18960307],
        [2.99943987, 3.59564505, 0.95734174],
        [2.95526093, 3.77641876, 0.50500734],
        [3.09159897, 3.95333442, 0.87442768],
        [2.66522908, 3.34553844, 0.20265769]
    ]
])

np.einsum('ijk,ik->ij', t, normal)

This results in

array([[ 3.52050429,  3.02851036,  1.39539629,  1.44869879,  4.9411858 ,
         2.05224039,  4.50264332,  3.47096686,  5.16705551,  1.24011516],
       [22.69703871, 23.46350713, 21.76853041, 21.98926093, 26.07809129,
        23.47223475, 24.81159677, 24.75511727, 26.64957859, 21.46600189]])

Which is the same as doing the two multiplications in order:

t[0] @ normal[0] 
t[1] @ normal[1] 

Gives the two:

array([3.52050429, 3.02851036, 1.39539629, 1.44869879, 4.9411858 ,
       2.05224039, 4.50264332, 3.47096686, 5.16705551, 1.24011516])
array([22.69703871, 23.46350713, 21.76853041, 21.98926093, 26.07809129,
       23.47223475, 24.81159677, 24.75511727, 26.64957859, 21.46600189])
Answered By: Mark