在Python中构建矩阵的快速方法(Fast way to construct a matrix in Python)

编程入门 行业动态 更新时间:2024-10-25 12:28:03
在Python中构建矩阵的快速方法(Fast way to construct a matrix in Python)

我一直在浏览这些问题,并且可以找到一些帮助,但我更喜欢直接询问确认。 所以这是我的问题。

我有一个维度为N的(numpy)数组u ,我想从中建立一个维数为N ^ 2的方阵k 。 基本上,每个矩阵元素k(i,j)被定义为k(i,j)=exp(-|u_i-u_j|^2) 。

我的第一个天真的方式是这样的,我相信,这是Fortran:

for i in range(N): for j in range(N): k[i][j]=np.exp(np.sum(-(u[i]-u[j])**2))

但是,这非常慢。 例如,对于N = 1000,它需要大约15秒。 我的另一种继续方式是以下(受其他问题/答案的启发):

i, j = np.ogrid[:N,:N] k = np.exp(np.sum(-(u[i]-u[j])**2,axis=2))

这样更快,因为N = 1000,结果几乎是瞬时的。 所以我有两个问题。

1)为什么第一种方法如此之慢,为什么第二种方法如此之快?

2)有更快的方法吗? 对于N = 10000,它已经开始花了相当长的时间,所以我真的不知道这是否是“正确”的方式。

先谢谢你 !

PS:矩阵是对称的,所以还必须有一种方法通过仅计算矩阵的上半部分来使处理更快,但我的问题更多地与操纵数组的方式等有关。

I have been browsing through the questions, and could find some help, but I prefer having confirmation by asking it directly. So here is my problem.

I have an (numpy) array u of dimension N, from which I want to build a square matrix k of dimension N^2. Basically, each matrix element k(i,j) is defined as k(i,j)=exp(-|u_i-u_j|^2).

My first naive way to do it was like this, which is, I believe, Fortran-like:

for i in range(N): for j in range(N): k[i][j]=np.exp(np.sum(-(u[i]-u[j])**2))

However, this is extremely slow. For N=1000, for example, it is taking around 15 seconds. My other way to proceed is the following (inspired by other questions/answers):

i, j = np.ogrid[:N,:N] k = np.exp(np.sum(-(u[i]-u[j])**2,axis=2))

This is way faster, as for N=1000, the result is almost instantaneous. So I have two questions.

1) Why is the first method so slow, and why is the second one so fast ?

2) Is there a faster way to do it ? For N=10000, it is starting to take quite some time already, so I really don't know if this was the "right" way to do it.

Thank you in advance !

P.S: the matrix is symmetric, so there must also be a way to make the process faster by calculating only the upper half of the matrix, but my question was more related to the way to manipulate arrays, etc.

最满意答案

首先,一个小注释,如果u可以重写为u = np.arange(N) ,则不需要使用np.sum 。 这似乎就是这种情况,因为你写的它是维度N

1)第一个问题:在Python中访问索引很慢,所以如果有办法不使用它,最好不要使用[]。 另外,你多次调用np.exp和np.sum ,而它们可以被称为向量和矩阵。 因此,您的第二个提案更好,因为您只需一次计算k ,而不是按元素计算元素。

2)第二个问题:是的。 您应该考虑仅使用numpy函数而不使用索引(大约快3倍):

k = np.exp(-np.power(np.subtract.outer(u,u),2))

(注意:你可以保持**2而不是np.power ,这有点快,但精度np.power )


编辑 (考虑到u是一个元组数组)

使用元组数据,它有点复杂:

ma = np.subtract.outer(u[:,0],u[:,0])**2 mb = np.subtract.outer(u[:,1],u[:,1])**2 k = np.exp(-np.add(ma, mb))

你将不得不使用两次np.substract.outer因为如果你一次这样做它会返回一个4维数组(并计算大量无用数据),而u[i]-u[j]返回3维阵列。

我使用np.add而不是np.sum因为它保留了数组维度。

NB:我查了一下

N = 10000 u = np.random.random_sample((N,2))

我返回与您的提案相同的内容。 (但快1.7倍)

First, a small remark, there is no need to use np.sum if u can be re-written as u = np.arange(N). Which seems to be the case since you wrote that it is of dimension N.

1) First question: Accessing indices in Python is slow, so best is to not use [] if there is a way to not use it. Plus you call multiple times np.exp and np.sum, whereas they can be called for vectors and matrices. So, your second proposal is better since you compute your k all in once, instead of elements by elements.

2) Second question: Yes there is. You should consider using only numpy functions and not using indices (around 3 times faster):

k = np.exp(-np.power(np.subtract.outer(u,u),2))

(NB: You can keep **2 instead of np.power, which is a bit faster but has smaller precision)


edit (Take into account that u is an array of tuples)

With tuple data, it's a bit more complicated:

ma = np.subtract.outer(u[:,0],u[:,0])**2 mb = np.subtract.outer(u[:,1],u[:,1])**2 k = np.exp(-np.add(ma, mb))

You'll have to use twice np.substract.outer since it will return a 4 dimensions array if you do it in one time (and compute lots of useless data), whereas u[i]-u[j] returns a 3 dimensions array.

I used np.add instead of np.sum since it keep the array dimensions.

NB: I checked with

N = 10000 u = np.random.random_sample((N,2))

I returns the same as your proposals. (But 1.7 times faster)

更多推荐

本文发布于:2023-08-05 19:19:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1437768.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:矩阵   快速   方法   Python   construct

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!