Внешняя сумма координат - PullRequest
0 голосов
/ 31 мая 2019

У меня есть два массива:

# A
[[0 3]
 [2 3]
 [3 1]]

# B
[[2  0]
 [0 -1]
 [0  1]
 [1  0]]

Результатом должна быть внешняя сумма по координатам:

[[2 3],[0 2],[0 4],[1 3]], # [0 3] + each element of B
[[4 3],[2 2],[2 4],[3 3]],
[[5 1],[3 0],[3 2],[4 1]]

Мне удалось решить это с помощью циклов, однако для работы с большими матрицами необходима векторизованная реализация. Я подошел к этому с внешней суммой, но безуспешно.

for i in A:
    for j in B:
        print(i+j)

1 Ответ

3 голосов
/ 01 июня 2019

Просто увеличьте 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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...