I have a function that takes a four-dimensional NumPy array M and, for each value i of its second index, takes all of M without the i-th "column", evaluates the product over all other columns, and stacks the results so that the array returned has the same shape as M.
In other words, what I want to evaluate is:
$$R_{ijkl} = \prod_{j^l \ne j} M_{ij^{l}kl}$$
My main concern is performance: M's shape is usually something similar to (16,8,1000,255)
and this function call takes up the great majority of my program's execution time.
import numpy as np
def sliceAndMultiply(M):
# create masks
masks = [ range(i) + range(i+1, M.shape[1]) for i in range(M.shape[1]) ]
# evaluate products over masks and stack them
return np.stack([ np.prod(M[:,m,:,:], axis=1) for m in masks ], axis=1)
M = np.random.rand(16,8,1000,255)
R = sliceAndMultiply(M)
Another variant I tried is:
def sliceAndMultiply(M):
return np.stack([ np.prod(np.delete(M, j, axis=1), axis=1) \
for j in range(M.shape[1]) ], axis=1)
but the performance of these two functions is basically the same.