I have an array x of shape (N, T, d). I have two functions f and g which both take an array of shape (some_dimension, d) and return an array of shape (some_dimension, ).
I would like to compute f on all of x. This is simple: f(x.reshape(-1, d)).
I would then like to compute g only on the first slice of the second dimension, meaning g(x[:, 0, :]) and subtract this to the evaluation of f on for all dimensions. This is exemplified in the code
MWE - Inefficient Way
import numpy as np
# Reproducibility
seed = 1234
rng = np.random.default_rng(seed=seed)
# Generate x
N = 100
T = 10
d = 2
x = rng.normal(loc=0.0, scale=1.0, size=(N, T, d))
# In practice the functions are not this simple
def f(x):
return x[:, 0] + x[:, 1]
def g(x):
return x[:, 0]**2 - x[:, 1]**2
# Compute f on all the (flattened) array
fx = f(x.reshape(-1, d)).reshape(N, T)
# Compute g only on the first slice of second dimension. Here are two ways of doing so
gx = np.tile(g(x[:, 0])[:, None], reps=(1, T))
gx = np.repeat(g(x[:, 0]), axis=0, repeats=T).reshape(N, T)
# Finally compute what I really want to compute
diff = fx - gx
Is there a more efficient way? I feel that using broadcasting there must be, but I cannot figure it out.
Reducing the size of the example so we can examine (5,4) arrays:
All the elements of
fxdiffer, so no further 'broadcasting' is possible.Your use of
tileandrepeatdo the same thing.tileusesrepeat, so doesn't add anything:gxjust repeats the 5g()values 4 times.So
gxcan be replaced with a (5,1) array, which broadcasts with the (5,4)fx:I haven't tried to make more sense of the
Tversusddimensions that I commented on.This answer may be too wordy, but it illustrates the way I visualized and discovered a
broadcastingfix.