给定一个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
。
答案 0 :(得分:19)
怎么样:
>>> 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是一个视图(它没有自己的副本,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
答案 1 :(得分:2)
您可以使用
计算所有元素的平方并按列顺序求和np.sum(np.square(A),0);
(我不完全确定sum
函数的第二个参数,它标识了取总和的轴,我当前没有安装任何numpy。也许你必须试验: )...)
修改强>
查看 DSM 的帖子,您似乎应该使用axis=0
。使用square
函数可能比使用A*A
更高效。
答案 2 :(得分:0)
从线性代数中,行i与行j的点积是AA ^ T的第i个,第j个条目。类似地,列i与列j的点积是(A ^ T)A的第i个条目。
因此,如果您想要A的每个列向量的点积,您可以使用ColDot = np.dot(np.transpose(A), A).diagonal()
。另一方面,如果您想要每行的点积,您可以使用RowDot = np.dot(A, np.transpose(A)).diagonal()
。
两行都返回一个数组。