Использование numy einsum для вычисления внутреннего произведения векторов-столбцов матрицы
Предположим, у меня есть такая матрица:
[[ 1 2 3]
[ 10 100 1000]]
Я хотел бы вычислить внутренний продукт каждого столбца с самим собой, поэтому результат будет:
[1*1 + 10*10 2*2 + 100*100 3*3 + 1000*1000] == [101, 10004, 1000009]
Я хотел бы знать, возможно ли это с помощью einsum
функция (и чтобы лучше понять это).
Пока что ближайший результат, который я мог бы получить:
import numpy as np
arr = np.array([[1, 2, 3], [10, 100, 1000]])
res = np.einsum('ij,ik->jk', arr, arr)
# [[ 101 1002 10003]
# [ 1002 10004 100006]
# [ 10003 100006 1000009]]
Диагональ содержит ожидаемый результат, но я хотел бы знать, могу ли я избежать расчетов ребер.
2 ответа
Использование np.einsum
, вот так -
np.einsum('ij,ij->j',arr,arr)
Пробный прогон -
In [243]: np.einsum('ij,ij->j',arr,arr)
Out[243]: array([ 101, 10004, 1000009])
Или с np.sum
-
In [244]: (arr**2).sum(0)
Out[244]: array([ 101, 10004, 1000009])
Или с numexpr
модуль -
In [248]: import numexpr as ne
In [249]: ne.evaluate('sum(arr**2,0)')
Out[249]: array([ 101, 10004, 1000009])
То, что вы ожидаете здесь, можно понять интуитивно, с одним промежуточным шагом от ответа einsum Дивакара.
In [19]: arr
Out[19]:
array([[ 1, 2, 3],
[ 10, 100, 1000]])
# simply take element-wise product with the array itself
In [20]: np.einsum('ij, ij -> ij', arr, arr)
Out[20]:
array([[ 1, 4, 9],
[ 100, 10000, 1000000]])
Но это не дает ожидаемого результата. Итак, если вы наблюдаете приведенный выше результат, нам просто нужно сложить по первому измерению (то есть по оси 0). Итак, мы опускаем индекс i
после ->
в результате einsum, что означает, что мы просим его суммировать по этой оси, и это дает ожидаемый результат, который:
In [21]: np.einsum('ij, ij -> j', arr, arr)
Out[21]: array([ 101, 10004, 1000009])
PS Также для общего понимания np.einsum
смотрите подробное обсуждение здесь: понимание-numpy-einsum