NumPy:按列计算点积

16

给定一个二维的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个回答

22

怎么样:

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

这种方法似乎更快一些。这应该可以在幕后完成你想要的操作,因为A.T是一个视图(如果我理解正确,则不会生成自己的副本),并且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

"inner1d" 看起来正是所需之物。谢谢。 - NPE

2

您可以使用以下方法计算所有元素的平方并按列求和:

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

我不完全确定sum函数的第二个参数,它用来指定沿哪个轴进行求和,并且我目前没有安装numpy。也许你需要尝试一下 :) ...

编辑

看到 DSM 的帖子,似乎应该使用axis = 0。使用square函数可能比使用A*A更有效率。


0

从线性代数的角度来看,第i行和第j行的点积是AA^T的第i,j个元素。同样地,第i列和第j列的点积是(A^T)A的第i,j个元素。

因此,如果您想要计算A的每个列向量与其自身的点积,您可以使用ColDot = np.dot(np.transpose(A), A).diagonal()。另一方面,如果您想要计算每行向量与其自身的点积,您可以使用RowDot = np.dot(A, np.transpose(A)).diagonal()

这两行代码都会返回一个数组。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接