2014-11-22 60 views
2
Y, X = np.mgrid[-3:-3:10j, -3:3:10j] 

我注意到當在上面的meshgrids上應用某些操作時,我得到一個錯誤,因爲操作可能與numpy不兼容。有時可能會有一個numpy函數替代sin,cos,但不是像scipy.integrate中的四元函數那樣的所有函數。numpy meshgrid操作問題

我該如何解決這個問題?我需要對整個meshgrids進行操作。

+3

目前尚不清楚你的意思,當你說你需要應用'quad'到每個點在'meshgrid'中。 'quad'需要一個函數來進行整合,並且要求有限積分。有'integrate.nquad'接受一個多元函數,並且一個稱爲'ranges'的結構爲每個座標軸提供了積分極限。但是不清楚你想從你的問題中計算出什麼。 – ely 2014-11-22 20:36:37

+0

嗨。我其實並沒有舉出我的真實例子,因爲代碼太長,但例如說我有一個名爲MATHOPERATION(x,y)的函數,它需要兩個數字x和y,並輸出另一個數字。其中x和y是X和Y中在網格中佔據相同位置的數字。因此,MATHOPERATION(X,Y)的輸出將是一個與X和Y大小相同的網格網格。 – user3065619 2014-11-22 23:38:45

+0

當這些操作不是直接在ndarrays之上構建,或者以C代碼或使用Numba之類的工具構建或Cython,那麼就無法「矢量化」它們來操作存儲在meshgrid數組中的連續內存。最好的辦法就是在i和j(行,列)上編寫一個for循環,調用你的函數,並將其結果寫入一些預先分配的二維數組中。重複的函數調用將會很慢,如果你對它進行配置並且速度太慢,你將需要使用像numba這樣的東西,或者用C編寫它。 – ely 2014-11-23 00:01:29

回答

3

你的問題(與後續評論)可以採取至少兩種不同的方式:

  1. 你有多個參數的函數,你希望能夠調用該函數這種方式在語法上類似於numpy本機支持的廣播調用。性能不是問題,只是函數的調用語法。

  2. 您有一個函數需要在一系列numpy數組上進行評估,但函數沒有以可以利用numpy數組的連續內存佈局的方式實現。表現是問題;你會很樂意循環遍歷numpy數組,並且以無聊簡單的舊for循環風格調用你的函數,除非這樣做太慢。

對於項目1.有通過numpy的提供一個方便的功能,稱爲vectorize這需要經常調用和返回Callable可與numpy的數組作爲參數調用,並服從numpy的廣播規則。

考慮這個人爲的例子:

def my_func(x, y): 
    return x + 2*y 

現在假設我需要在2 d電網到處評估此功能。這裏是普通的老無聊的方式:

Y, X = np.mgrid[0:10:1, 0:10:1] 
Z = np.zeros_like(Y) 

for i in range(Y.shape[0]): 
    for j in range(Y.shape[1]): 
     Z[i,j] = my_func(X[i,j], Y[i,j]) 

如果我們有像my_func幾個不同的功能,它可能是不錯的概括這一過程變成一個功能,「映射」在2-d陣列給定函數。

import itertools 
def array_map(some_func, *arg_arrays): 
    output = np.zeros_like(arg_arrays[0]) 
    coordinates = itertools.imap(range, output.shape) 
    for coord in itertools.product(coordinates): 
     args = [arg_array[coord] for arg_array in arg_arrays] 
     output[coord] = some_func(*args) 
    return output 

現在我們可以看到,array_map(my_func, X, Y)行爲就像嵌套的循環:

In [451]: array_map(my_func, X, Y) 
Out[451]: 
array([[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 
     [ 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], 
     [ 4, 5, 6, 7, 8, 9, 10, 11, 12, 13], 
     [ 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], 
     [ 8, 9, 10, 11, 12, 13, 14, 15, 16, 17], 
     [10, 11, 12, 13, 14, 15, 16, 17, 18, 19], 
     [12, 13, 14, 15, 16, 17, 18, 19, 20, 21], 
     [14, 15, 16, 17, 18, 19, 20, 21, 22, 23], 
     [16, 17, 18, 19, 20, 21, 22, 23, 24, 25], 
     [18, 19, 20, 21, 22, 23, 24, 25, 26, 27]]) 

現在,那豈不是很好,如果我們可以稱之爲array_map(my_func)並留下關閉多餘的數組變量?取而代之的是取回一個剛剛等待執行所需for循環的新函數。因爲如果你能

In [453]: my_awesome_func = vectorizer(my_func) 

In [454]: my_awesome_func(X, Y) 
Out[454]: 
array([[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 
     [ 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], 
     [ 4, 5, 6, 7, 8, 9, 10, 11, 12, 13], 
     [ 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], 
     [ 8, 9, 10, 11, 12, 13, 14, 15, 16, 17], 
     [10, 11, 12, 13, 14, 15, 16, 17, 18, 19], 
     [12, 13, 14, 15, 16, 17, 18, 19, 20, 21], 
     [14, 15, 16, 17, 18, 19, 20, 21, 22, 23], 
     [16, 17, 18, 19, 20, 21, 22, 23, 24, 25], 
     [18, 19, 20, 21, 22, 23, 24, 25, 26, 27]]) 

現在my_awesome_func的行爲:

import functools 
def vectorizer(regular_function): 
    awesome_function = functools.partial(array_map, regular_function) 
    return awesome_function 

和測試出來:這樣我們就可以編寫一個方便的小矢量化這樣的 -

我們可以functools.partial做到這一點直接在ndarrays上調用它!

我忽略了很多額外的小表現細節,邊界檢查等。,同時使這個玩具版本叫vectorizer ...但幸運的是在numpy有vectorize已經做到這一點!

In [455]: my_vectorize_func = np.vectorize(my_func) 

In [456]: my_vectorize_func(X, Y) 
Out[456]: 
array([[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 
     [ 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], 
     [ 4, 5, 6, 7, 8, 9, 10, 11, 12, 13], 
     [ 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], 
     [ 8, 9, 10, 11, 12, 13, 14, 15, 16, 17], 
     [10, 11, 12, 13, 14, 15, 16, 17, 18, 19], 
     [12, 13, 14, 15, 16, 17, 18, 19, 20, 21], 
     [14, 15, 16, 17, 18, 19, 20, 21, 22, 23], 
     [16, 17, 18, 19, 20, 21, 22, 23, 24, 25], 
     [18, 19, 20, 21, 22, 23, 24, 25, 26, 27]]) 

再次,如強調我早些時候的評論到OP和文檔在vectorize - 這不是的速度優化。實際上,在某些情況下,額外的函數調用開銷會比直接編寫for循環慢。但是,對於速度不是問題的情況,這種方法確實可以讓您的自定義函數遵循與numpy相同的調用約定 - 這可以提高庫的接口的一致性,並使代碼更加一致且更具可讀性。

關於第2項已經寫了很多其他的東西。如果你的問題是你需要優化你的函數以利用連續的內存塊並通過重複的動態類型檢查(numpy數組的主要特性添加到Python列表),那麼這裏有幾個鏈接對您有幫助:

  1. < http://pandas.pydata.org/pandas-docs/stable/enhancingperf.html>
  2. < http://csl.name/C-functions-from-Python/>
  3. < https://jakevdp.github.io/blog/2014/05/09/why-python-is-slow>
  4. < nbviewer.ipython.org/url/jakevdp.github.io/downloads/notebooks/NumbaCython.ipynb>
+0

嗨prpl。我嘗試了forloop技巧,但它不適用於我正在使用的特定功能。我在這裏提出了一個關於它的新問題:http://stackoverflow.com/questions/27091037/numpy-iterating-calculations-in-a-meshgrid – user3065619 2014-11-23 16:50:20

+1

當數學運算導致值過大時發生'OverflowError'被代表。根據名字'Emag'判斷,我猜測這是一些電磁網格計算 - 也許如果你的函數涉及到極點,那麼你正試圖計算一個太接近極點的值並且數值溢出。無論哪種方式,這與網格計算的問題無關,而是與在'Emag'定義中使用數學運算相關的錯誤。 – ely 2014-11-23 18:05:53