Давайте создадим более простой тестовый массив:
In [254]: A = np.arange(10).reshape(2,5)
In [255]: A
Out[255]:
array([[0, 1, 2, 3, 4],
[5, 6, 7, 8, 9]])
In [256]: A.shape
Out[256]: (2, 5)
Учитывая способ описания проблемы, np.outer
должно быть легко применимо:
In [257]: np.outer(A[0],A[0])+np.outer(A[1],A[1])
Out[257]:
array([[25, 30, 35, 40, 45],
[30, 37, 44, 51, 58],
[35, 44, 53, 62, 71],
[40, 51, 62, 73, 84],
[45, 58, 71, 84, 97]])
np.outer
работает толькос 1d массивами, а не целыми 2d A
.Но мы можем сделать то же самое outer
, используя broadcasting
.Результатом будет массив (2,5,5), который мы затем можем суммировать по первой оси:
In [260]: (A[:,:,None]*A[:,None,:]).sum(axis=0)
Out[260]:
array([[25, 30, 35, 40, 45],
[30, 37, 44, 51, 58],
[35, 44, 53, 62, 71],
[40, 51, 62, 73, 84],
[45, 58, 71, 84, 97]])
np.einsum
также является удобным способом описания операций такого типа (если выиспользуются для работы с индексами оси):
In [261]: np.einsum('ij,ik->jk',A,A)
Out[261]:
array([[25, 30, 35, 40, 45],
[30, 37, 44, 51, 58],
[35, 44, 53, 62, 71],
[40, 51, 62, 73, 84],
[45, 58, 71, 84, 97]])
Но это einsum
, безусловно, выглядит как dot
продукт, сумма продуктов.Нам просто нужно транспонировать первый массив:
np.einsum('ji,ik->jk', A.T,A)
или np.dot
:
In [262]: np.dot(A.T,A)
Out[262]:
array([[25, 30, 35, 40, 45],
[30, 37, 44, 51, 58],
[35, 44, 53, 62, 71],
[40, 51, 62, 73, 84],
[45, 58, 71, 84, 97]])