1
votes

I am trying to do a matrix multiplication with a tensor, but I'm uncertain how to do it with Numpy. I have been trying to work with np.tensordot(), but I haven't been able to do so

In a simpler way, if we were to do matrix multiplications and we had a vector v (Nx1) and a matrix S (NxN), we can do the operation

v^T S v => (1xN)(NxN)(Nx1) => a number

v = np.ones((3,1))
S = np.ones((3,3))
y = v.T.dot(S).dot(v)
y.shape = (1) or ()

Now, I'd like to do the following:

Let matrix M (3x5) and tensor Z (5x3x3) so that I can have
M^T Z M
where (M^T Z) yields a (5x3) matrix, and M^T Z M yields a (1x5) vector

M = np.ones((3,5))
Z = np.ones((5,3,3))
Y = <?> M.T * Z * M <?>
Y.shape = (5,) or (1,5)

Does anyone know how to do this using Numpy without using Tensorflow?

1
Have you looked at np.einsum?hpaulj
The rule of thumb for dot is the the last dim of A pairs with the 2nd to the last of B. Clarify for us, which dimensions of M (or M.T) pair with which of Z and M. I can guess, but I think you need to be explicithpaulj
I've played a little with eigensum and I obtained different results, all with shape (1,5) or (5,). I think that you should tell which is your expected result or give a reference implementation using loops.gboffi

1 Answers

0
votes

I think this computes what you want:

import numpy as np

M = np.ones((3, 5))
Z = np.ones((5, 3, 3))
# Multiply (5, 1, 3) x (5, 3, 3) x (5, 3, 1)
result = (M.T[:, np.newaxis] @ Z @ M.T[:, :, np.newaxis]).squeeze()
print(result)

Output:

[9. 9. 9. 9. 9.]

I have used the @ operator for convenience, but you can replace it with np.matmul if you like it more or are using an older Python version:

result = np.matmul(np.matmul(M.T[:, np.newaxis], Z), M.T[:, :, np.newaxis]).squeeze()