Reputation: 934
I have two numpy arrays, X
and Y
whose shapes are X.shape == (m,d)
and Y.shape == (n,d)
, where m
, n
, and d
are non-trivial sizes. I need to make a third array Z
whose shape is Z.shape == (m,n)
.
An element Z[i,j]
is the result of taking f(X[i,k],Y[j,k]) for k in range(d)
and then summing over all k
, for some non-linear f
.
The obvious way to do this is to do this:
Z = numpy.zeros((m,n), dtype = numpy.float64)
for i in range(m):
for j in range(n):
Z[i,j] += (f(X[i,:],Y[j,:])).sum() # I can compose f from ufuncs
but what I'm really asking is whether there's some kind of clever broadcasting trick that I can use to compute Z
that will:
(n,m,d)
in memory (n*m
doubles will fit in memory, but n*m*d
doubles won't)Does anyone know of a way to do this? Thanks in advance.
Upvotes: 2
Views: 81
Reputation: 25813
Here is the solution you don't want, I've included it because I believe this is the "canonical" solution to your problem.
# A simple function of x, y
def f(x, y):
return 2*x + 3*y**2
x = x.reshape((m, 1, d))
y = y.reshape((1, n, d))
temp = f(x, y)
Z = temp.sum(2)
If you want to avoid creating the temporary array temp
, which is quite large, you could try looping over the d
dimension. In some cases the overhead of the following loop will be quite small and you'll get almost the same performance, with much less memory usage.
Z = np.zeros((m, n))
for i in range(d):
Z += f(x[:, :, i], y[:, :, i])
Let me know if that helps.
Upvotes: 1