NumPy: столбец точечный продукт

Учитывая 2D numpy массив, мне нужно вычислить скалярное произведение каждого столбца с самим собой и сохранить результат в одномерном массиве. Следующие работы:

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 Примитивно для этого, я хотел бы использовать его.

На практике матрица имеет много строк и относительно мало столбцов. Поэтому я не слишком заинтересован в создании временных массивов, превышающих O(A.shape[1]), Я тоже не могу изменить A на месте.

3 ответа

Решение

Как насчет:

>>> A = np.array([[1,2,3,4],[5,6,7,8]])
>>> (A*A).sum(axis=0)
array([26, 40, 58, 80])

РЕДАКТИРОВАТЬ: Хм, хорошо, вы не хотите промежуточные крупные объекты. Может быть:

>>> 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])

который кажется немного быстрее в любом случае. Это должно делать то, что вы хотите за кулисами, так как AT - это представление (которое не создает свою собственную копию, 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

Вы можете вычислить квадрат всех элементов и суммировать по столбцам, используя

np.sum(np.square(A),0);

(Я не совсем уверен насчет второго параметра sum Функция, которая идентифицирует ось, вдоль которой берется сумма, и у меня в данный момент нет ничего кроссового. Может быть, вам придется экспериментировать:) ...)

РЕДАКТИРОВАТЬ

Глядя на пост DSM, кажется, что вы должны использовать axis=0, С использованием square функция может быть немного более производительной, чем при использовании A*A,

В линейной алгебре точечное произведение строки i на строку j является i, j-й записью AA^T. Аналогично, произведение точек столбца i на столбец j является i-й, j-й записью (A^T)A.

Поэтому, если вы хотите получить произведение точек каждого вектора столбца А на себя, вы можете использовать ColDot = np.dot(np.transpose(A), A).diagonal(), С другой стороны, если вы хотите получить точечное произведение каждой строки с самим собой, вы можете использовать RowDot = np.dot(A, np.transpose(A)).diagonal(),

Обе строки возвращают массив.

Другие вопросы по тегам