0

是否可以使用NumPy(和SciPy)向量化(或以其他方式加速)基於元素的優化?向量化元素明智

從最抽象的意義上說,我有一個函數y,它是拋物線形狀的,可以基本表示爲y=x^2+b*x+z,其中x是已知值的數組,並且我想要找到使最小值爲y完全爲零(換句話說,我想找到一個讓我的拋物線只有一個零的值z)。爲此,我選擇了一種簡單的類似二分法。造成這種情況的代碼如下:

import numpy as np 

def find_single_root(): 
    x = np.arange(-5, 6,0.1) # domain 
    z = 1 # initial guess 
    delta = 1 # initial step size 
    tol = 0.001 # tolerance 
    while True: 
     y = x**2-5*x+z 
     minimum = np.nanmin(y) 
     # update z 
     print(delta) 
     print(z) 
     if minimum > 0: 
      if delta > 0: 
       delta = -1*delta/2 
      z += delta 
     else: 
      if delta < 0: 
       delta = -1*delta/2 
      z += delta 
     # check if step is smaller than tolerance 
     if np.abs(delta) < tol: 
      return z 

現在讓我們說X(V,W),和我想創建z值的2D陣列,其中,每個被優化。我現在所擁有的下方是(注意,新的函數定義和域如下)

def find_single_root(v, w): 
    x = np.arange(-5*v/w, 6*w,0.1) # domain 
    ... # rest of the function 

vs = np.arange(1,5) 
ws = np.arange(1,5) 
zs = np.zeros((len(vs),len(ws))) 
for i, v in enumerate(vs): 
    for j, w in enumerate(ws): 
     zs[i][j] = find_single_root(v,w) 

現在我只是有這些簡單的嵌套的循環,但有一種方法,我用另一種方式這或速度它與NumPy矢量化?

回答

0

當預先準確知道要執行的計算時,矢量化可能適用。就像「採用兩組數字,並將它們相乘」。

當計算修改爲給定數據時,矢量化不適用。任何一種優化算法都是自適應的,因爲在哪裏尋找最小值取決於函數返回的內容。如果你有一堆函數,並且需要找到每個函數的最小值,那麼你將不得不一次一個地最小化它們,在一個循環中。如果這個過程很慢,那是因爲它需要很長時間來最小化一堆函數,而不是因爲程序中有一個for循環。

關於你的計劃,我會嘗試使用一些SciPy的方法都最小化和求根。有一個函數min_of_f(z),該函數可以使用minimize_scalar找到參數z給定值的最小值。然後將min_of_f送到root-finding routine。這些需要多長時間可以通過它們的公差參數(xtol和其他)來控制。


OP編輯: 我想給信貸這是一個正確的答案,但依然提供更多信息。

我結束了使用numpy.vectorize沒有重組問題向量化。雖然numpy.vectorize並不意味着提高性能,但在我的具體使用情況下,性能是兩個速度更快的溫和因素。對問題中的原始問題應用相同的方法導致實際上沒有加速100x100矢量,因此YMMV。

即使我無法從上面的答案給出的原因的速度方面矢量化這個問題,能夠使用純矢量語法代替嵌套的for循環都在我的代碼是有益的。

+0

感謝您的回答。在我的實際問題中計算y的數值複雜性足夠重要,因此對其進行矢量化可使整個優化函數提高60倍。我明白你對於自適應方法的含義,這就是爲什麼我問是否有另一種解決方法來解決這個問題,這是可以進行矢量化的。最終,我可以在Cython中重寫這一點,但這種努力不值得提升性能。 –