numpy:按列点积

发布于 2024-11-13 09:48:54 字数 420 浏览 1 评论 0原文

给定一个 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 原语可以实现这一点,我想使用它。

编辑 实际上,矩阵有很多行和相对较少的列。因此,我不太热衷于创建大于 O(A.shape[1]) 的临时数组。我也无法就地修改 A

Given a 2D numpy array, I need to compute the dot product of every column with itself, and store the result in a 1D array. The following works:

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

Is there a simple way to avoid the Python loop? The above is hardly the end of the world, but if there's a numpy primitive for this, I'd like to use it.

edit In practice the matrix has many rows and relatively few columns. I am therefore not overly keen on creating temporary arrays larger than O(A.shape[1]). I also can't modify A in place.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

糖粟与秋泊 2024-11-20 09:48:54

怎么样:

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

How about:

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

EDIT: Hmm, okay, you don't want intermediate large objects. Maybe:

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

which seems a little faster anyway. This should do what you want behind the scenes, as A.T is a view (which doesn't make its own copy, IIUC), and inner1d seems to loop the way it needs to.

VERY BELATED UPDATE: Another alternative would be to use 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
原谅我要高飞 2024-11-20 09:48:54

您可以计算所有元素的平方并使用逐列求和

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

(我不完全确定 sum 函数的第二个参数,它标识求和所沿的轴,并且我当前没有安装 numpy,也许你必须尝试一下:) ...)

编辑

看看DSM的帖子,似乎你应该使用轴=0。使用 square 函数可能比使用 A*A 的性能更高一些。

You can compute the square of all elements and sum up column-wise using

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

(I'm not entirely sure about the second parameter of the sum function, which identifies the axis along which to take the sum, and I have no numpy currently installed. Maybe you'll have to experiment :) ...)

EDIT

Looking at DSM's post, it seems that you should use axis=0. Using the square function might be a little more performant than using A*A.

自由如风 2024-11-20 09:48:54

根据线性代数,第 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()。

这两行都返回一个数组。

From linear algebra, the dot product of row i with row j is the i,j th entry of AA^T. Similarly, the dot product of column i with column j is the i,jth entry of (A^T)A.

So if you want the dot product of each column vector of A with itself, you could use ColDot = np.dot(np.transpose(A), A).diagonal(). On the other hand, if you want the dot product of each row with itself, you could use RowDot = np.dot(A, np.transpose(A)).diagonal().

Both lines return an array.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文