2017-06-13 81 views
0

我在Python中构建矩阵时遇到了一些问题。 每个元素中都有一个循环,其中each element A_{ij}的形式如图所示,这里x是一个q元素的数组(在下面的代码中用xi表示)。Python:如何避免构建这个矩阵的循环,并更快地计算它的行​​列式?

我尝试了下面的代码,但它需要太多的时间。我认为这是因为循环的数量,所以我在考虑将它看作两个矩阵的产品,但由于lambda具有两个维度,所以它不起作用。

由于这些代码将作为一个函数显示并将被多次使用,有什么方法可以让它变得更快?谢谢sooooo多!

def lambdak(i,j,alpha,rho): 
    return math.pi * alpha**2 * rho * math.exp(-math.pi**2 * alpha**2 *(i**2 + j**2)) 
def phik(i,j,x,alpha,rho): 
    return cmath.exp(2 * math.pi * 1j * (i*x[0] + j*x[1])) 
alpha = 0.5 
rho = 50 
num = 30 
x = np.random.uniform(-0.5,0.5,num) 
y = np.random.uniform(-0.5,0.5,num) 
xi = np.zeros((num,3)) 
for i in range(num): 
    xi[i] = np.array([x[i], y[i], 0]) 
q = len(xi) 
A = [[np.sum(list(map(lambda j: 
        np.sum(list(map(lambda i: 
            lambdak(i,j,alpha,rho)/(1-lambdak(i,j,alpha,rho))* phik(i,j,xi[x]-xi[y],alpha,rho), 
            range(-N,N+1)))), 
        range(-N,N+1)))) for x in range(q)] for y in range(q)] 
a = np.linalg.inv(A) 
+0

只要看看你的代码,我可以给你一些建议。 1)您可以将计算lambda表达式(i,j,alpha,rho)移入单独的函数中,并将其存储在二维数组中。你不必为每个q重新计算它。 2)此代码也可以并行化,您可以独立计算每个值,但python具有GIL限制。基本上,这意味着,即使你使用python实现多线程,你也不会看到明显的加速。但是有一些微妙的优化,比如缓存,这绝对可以让你的代码的订单更快。 – skippy

+0

@skippy thx这么多为您的答案!我会尝试第一点! –

+0

@skippy但是对于你的第二点,你能稍微解释一下吗?我研究过“缓存”,但由于我对它不熟悉,所以我完全失去了XO –

回答

0

正如您怀疑的那样,性能不佳的原因是您的循环。我假设你正在使用numpy,因为你在循环中调用np.sum。然后诀窍是将内部循环翻出来,而是将更大的结构(即矩阵)传递给numpy函数。

这样做可以显着加快性能。上面提出的代码,可被修改以:

import numpy as np 

def lambdak(i,j,alpha,rho): 
    return np.pi * alpha**2 * rho * np.exp(-math.pi**2 * alpha**2 *(i**2 + j**2)) 

def phik(i,j,x,alpha,rho): 
    return np.exp(2 * np.pi * 1j * (i*x[:, :, 0] + j*x[:, :, 1])) 

alpha = 0.5 
rho = 50 
num = 30 
x = np.random.uniform(-0.5,0.5,num) 
y = np.random.uniform(-0.5,0.5,num) 
xi = np.zeros((num,3)) 
for i in range(num): 
    xi[i] = np.array([x[i], y[i], 0]) 

X = np.arange(num).reshape(1,num) 
Y = np.arange(num).reshape(num,1) 

xi_diff = xi[X] - xi[Y] 

N = 30 

A = np.sum(map(lambda j: 
       np.sum(map(lambda i: 
         lambdak(i,j,alpha,rho)/(1-lambdak(i,j,alpha,rho))* phik(i,j,xi_diff,alpha,rho), 
         range(-N,N+1)), 0), 
        range(-N,N+1)), 0) 

a = np.linalg.inv(A) 

在这里,外环被转换成一个矩阵,其被作为一个整体来对numpy功能通过。此外,我预先计算xi_diff,因为每次调用都会传递整个结构(即使只有一部分被phik()使用)。

这给了一个戏剧性的加速。但是,计算中的数字稳定性可能会受到影响,并且当我比较两种方法的输出时,它们相差约0.1%。不过,希望这没问题。