I am looking to do the following operation in python (numpy).
Matrix A is M x N x R
Matrix B is N x 1 x R
Matrix multiply AB = C, where C is a M x 1 x R matrix. Essentially each M x N layer of A (R of them) is matrix multiplied independently by each N x 1 vector in B. I am sure this is a one-liner. I have been trying to use tensordot(), but I that seems to be giving me answers that I don't expect.
I have been programming in Igor Pro for nearly 10 years, and I am now trying to convert pages of it over to python.
A 3D matrix is nothing but a collection (or a stack) of many 2D matrices, just like how a 2D matrix is a collection/stack of many 1D vectors. So, matrix multiplication of 3D matrices involves multiple multiplications of 2D matrices, which eventually boils down to a dot product between their row/column vectors.
In Python to initialize a 3-dimension array, we can easily use the np. array function for creating an array and once you will print the 'arr1' then the output will display a 3-dimensional array.
For example X = [[1, 2], [4, 5], [3, 6]] would represent a 3x2 matrix. The first row can be selected as X[0] . And, the element in first row, first column can be selected as X[0][0] . Multiplication of two matrices X and Y is defined only if the number of columns in X is equal to the number of rows Y .
Sorry for the necromancy, but this answer can be substantially improved upon, using the invaluable np.einsum.
import numpy as np
D,M,N,R = 1,2,3,4
A = np.random.rand(M,N,R)
B = np.random.rand(N,D,R)
print np.einsum('mnr,ndr->mdr', A, B).shape
Note that it has several advantages: first of all, its fast. np.einsum is well-optimized generally, but moreover, np.einsum is smart enough to avoid the creation of an MxNxR temporary array, but performs the contraction over N directly.
But perhaps more importantly, its very readable. There is no doubt that this code is correct; and you could make it a lot more complicated without any trouble.
Note that the dummy 'D' axis can simply be dropped from B and the einsum statement if you wish.
numpy.tensordot() is the right way to do it:
a = numpy.arange(24).reshape(2, 3, 4)
b = numpy.arange(12).reshape(3, 1, 4)
c = numpy.tensordot(a, b, axes=[1, 0]).diagonal(axis1=1, axis2=3)
Edit: The first version of this was faulty, and this version computes more han it should and throws away most of it. Maybe a Python loop over the last axis is the better way to do it.
Another Edit: I've come to the conclusion that numpy.tensordot()
is not the best solution here.
c = (a[:,:,None] * b).sum(axis=1)
will be more efficient (though even harder to grasp).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With