bfgt
bfgt

Reputation: 307

Compute inner dot products of multidimensional numpy array elements

What is the most elegant way to compute "inner" dot products of a multidimensional numpy array?

Let's assume I have 2 arrays a and b both of shape (2, 2, 2) (could be (n, n, 2) with n>= 2) and I want to compute the inner_dot(a, b) with the following definition:

np.array([[np.dot(a[0, 0, :], b[0, 0, :]), np.dot(a[1, 0, :], b[1, 0, :])],
          [np.dot(a[0, 1, :], b[0, 1, :]), np.dot(a[1, 1, :], b[1, 1, :])]])

Here is an example:

a = np.arange(8).reshape(2, 2, 2)
b = np.arange(8).reshape(2, 2, 2)

Expected result:

array([[ 1, 41],
       [13, 85]])

Upvotes: 4

Views: 112

Answers (3)

Raphael
Raphael

Reputation: 224

Just for the sake of completeness, I run a quick comparison of the run time:

import numpy as np
import timeit

a = np.arange(1024).reshape(64, 8, 2)
b = np.arange(1024).reshape(64, 8, 2)

example_1 = lambda: (a*b).sum(-1).T
print(timeit.timeit(example_1, number=10000))

example_2 = lambda: np.einsum('ijk,ijk->ji',a,b)
print(timeit.timeit(example_2, number=10000))

example_3 = lambda: (a[:,:,None,:]@b[:,:,:,None])[...,0,0].T
print(timeit.timeit(example_1, number=10000))

On my comupter, the results are (in seconds):

example 1: 0.10384939999999787
example 2: 0.05444100000000063
example 3: 0.097186200000003

Upvotes: 1

Divakar
Divakar

Reputation: 221504

Use np.einsum -

In [54]: np.einsum('ijk,ijk->ji',a,b)
Out[54]: 
array([[ 1, 41],
       [13, 85]])

With @ opetator/ np.matmul -

In [16]: (a[:,:,None,:]@b[:,:,:,None])[...,0,0].T
Out[16]: 
array([[ 1, 41],
       [13, 85]])

Upvotes: 3

yatu
yatu

Reputation: 88226

You can directly multiply both arrays and sum along the last axis. Also since you want the top right corner of the output as np.dot(a[1, 0, :], b[1, 0, :]), rather than 0,1 and presumably in the same fashion for the off-diagonal elements, you can transpose the result to get as expected:

(a*b).sum(-1).T
array([[ 1, 41],
       [13, 85]])

Upvotes: 5

Related Questions