2017-06-13 80 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%。不過,希望這沒問題。