Просто увеличьте a
до 3D
, сохранив последнюю ось с последней из b
, и сложите их. Это будет использовать broadcasting
для векторизованного решения. Чтобы сделать расширение для более высоких измерений, мы можем использовать np.newaxis/None
.
Следовательно, просто сделайте -
a[:,None,:] + b[:, :]
Пропустив лишние последние оси, указанные в :'s
, мы останемся с -
a[:,None] + b
Схематически обозначено -
a[:,None,:] : m x 1 x n
b[:,:] : k x n
output : m x k x n
Для больших массивов мы также можем использовать numexpr
, который использует многоядерные процессоры. Для этого нам нужно перенести ранее перечисленный метод широковещания с небольшими изменениями, например так -
import numexpr as ne
ne.evaluate('a3D+b',{'a3D':a[:,None]})
Сроки -
In [17]: np.random.seed(0)
...: a = np.random.rand(1000,3)
...: b = np.random.rand(1000,3)
In [18]: %timeit a[:,None] + b
11 ms ± 92.7 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
In [19]: %timeit ne.evaluate('a3D+b',{'a3D':a[:,None]})
4.1 ms ± 95.1 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)