Numpy: продукт с точкой в столбце
Учитывая массив 2D numpy
, мне нужно вычислить произведение точек каждого столбца с самим собой и сохранить результат в массиве 1D. Следующие работы:
In [45]: A = np.array([[1,2,3,4],[5,6,7,8]])
In [46]: np.array([np.dot(A[:,i], A[:,i]) for i in xrange(A.shape[1])])
Out[46]: array([26, 40, 58, 80])
Есть ли простой способ избежать цикла Python? Вышеизложенное вряд ли конец света, но если для этого есть примитив numpy
, я бы хотел его использовать.
edit На практике матрица имеет много строк и относительно немного столбцов. Поэтому я не слишком заинтересован в создании временных массивов, больших O(A.shape[1])
. Я также не могу изменить A
на месте.
Ответы
Ответ 1
Как насчет:
>>> A = np.array([[1,2,3,4],[5,6,7,8]])
>>> (A*A).sum(axis=0)
array([26, 40, 58, 80])
EDIT: Хм, хорошо, вам не нужны промежуточные крупные объекты. Может быть:
>>> from numpy.core.umath_tests import inner1d
>>> A = np.array([[1,2,3,4],[5,6,7,8]])
>>> inner1d(A.T, A.T)
array([26, 40, 58, 80])
который кажется немного быстрее в любом случае. Это должно делать то, что вы хотите за кулисами, поскольку A.T - это представление (которое не делает его собственную копию, IIUC), а inner1d, похоже, работает так, как ему нужно.
ОЧЕНЬ СЛУЖЕБНОЕ ОБНОВЛЕНИЕ: Еще одна альтернатива - использовать np.einsum
:
>>> A = np.array([[1,2,3,4],[5,6,7,8]])
>>> np.einsum('ij,ij->j', A, A)
array([26, 40, 58, 80])
>>> timeit np.einsum('ij,ij->j', A, A)
100000 loops, best of 3: 3.65 us per loop
>>> timeit inner1d(A.T, A.T)
100000 loops, best of 3: 5.02 us per loop
>>> A = np.random.randint(0, 100, (2, 100000))
>>> timeit np.einsum('ij,ij->j', A, A)
1000 loops, best of 3: 363 us per loop
>>> timeit inner1d(A.T, A.T)
1000 loops, best of 3: 848 us per loop
>>> (np.einsum('ij,ij->j', A, A) == inner1d(A.T, A.T)).all()
True
Ответ 2
Вы можете вычислить квадрат всех элементов и суммировать по столбцу с помощью
np.sum(np.square(A),0);
(Я не совсем уверен во втором параметре функции sum
, который идентифицирует ось, по которой нужно взять сумму, и у меня нет установленного количества numpy. Возможно, вам придется экспериментировать:)...)
ИЗМЕНИТЬ
Посмотрев сообщение DSM, кажется, что вы должны использовать axis=0
. Использование функции square
может быть немного более результативным, чем использование A*A
.
Ответ 3
Из линейной алгебры точечное произведение строки я со строкой j является i, j-й записью AA ^ T. Точно так же точечный продукт столбца я со столбцом j является i, j-й записью (A ^ T) A.
Итак, если вы хотите, чтобы произведение точек каждого столбца вектора A с самим собой, вы можете использовать ColDot = np.dot(np.transpose(A), A).diagonal()
. С другой стороны, если вы хотите, чтобы произведение точек каждой строки было само по себе, вы могли бы использовать RowDot = np.dot(A, np.transpose(A)).diagonal()
.
Обе строки возвращают массив.