[英]Python finding local maxima/minima for multiple polynomials efficiently
我正在尋找一種有效的方法來找到給定/指定范圍/邊界中多個(> 100 萬)但獨立的四階多項式的局部最小值。
我有兩個要求:
R1:即使對 100 萬個不同的多項式方程也有效
R2:局部最小值精確到0.01(即2dp)
這是我使用scipy
創建的一些代碼。 沒關系,但我想知道在我進行並行編程之前是否有其他更好的包來執行這樣的任務。
為了說明我的問題,讓我們先從一個多項式開始:
下面我試圖在 (-5, 5) 范圍內找到 4x^4 + 6x^3 + 3x^2 + x + 5 的局部最小值。
在我的筆記本電腦上,大約需要 2 毫秒才能找到本地最小值(約為 -0.72770502)。
一個多項式的時間還可以,但我想要更快的東西,因為我需要定期執行此操作超過 100 萬次。
from scipy import optimize
import numpy as np
# Define a objective and gradient function for 4th order polynomial
# x is the value to be evaluated
# par is a numpy array of len 5 that specifies the polynomial coefficients.
def obj_grad_fun_custom(x,par):
obj = (np.array([x**4,x**3,x**2,x**1,1]) * par).sum()
grad = (np.array([4*x**3,3*x**2,2*x,1]) * par[:-1]).sum()
return obj, grad
# Try minimise an example polynomial of 4x^4 + 6x^3 + 3x^2 + x + 5
# with contrainted bound
res = optimize.minimize(
fun = obj_grad_fun_custom,
x0 = 0,
args=(np.array([4,6,3,1,5])), # polynomial coefficients
jac=True ,
bounds=[(-2, 10)],
tol=1e-10)
print(res.x)
# Timing (this takes about 2 ms for me)
%timeit optimize.minimize(fun = obj_grad_fun_custom, x0 = 0, args=(np.array([4,6,3,1,5])), jac=True, bounds=[(-5, 5)], tol=1e-10)
下面是我打算用 100 萬個不同的 4 階多項式定期做的事情,我想在本地最小化。 希望有人能指出我比scipy
更合適的包。 或者有什么替代方法? 謝謝!
# Multiple polynomials
result = [] # saving the local minima
poly_sim_no = 1000000 #ideally 1 million or even more
np.random.seed(0)
par_set = np.random.choice(np.arange(10), size=(poly_sim_no, 5), replace=True) #generate some order 4 polynomial coefficients
for a in par_set:
res = optimize.minimize(obj_grad_fun_custom, 0,args=(a), jac=True ,bounds=[(-5, 5)], tol=1e-10)
result.append(res.x)
print(result)
由於您要找到多項式的最小值,因此您可以利用以下事實:對多項式求導很容易,並且有許多很好的算法可以找到多項式的根。
以下是它的工作原理:
這是代碼:
import numpy as np
from numpy.polynomial import Polynomial
def find_extrema(poly, bounds):
deriv = poly.deriv()
extrema = deriv.roots()
# Filter out complex roots
extrema = extrema[np.isreal(extrema)]
# Get real part of root
extrema = np.real(extrema)
# Apply bounds check
lb, ub = bounds
extrema = extrema[(lb <= extrema) & (extrema <= ub)]
return extrema
def find_minimum(poly, bounds):
extrema = find_extrema(poly, bounds)
# Note: initially I tried taking the 2nd derivative to filter out local maxima.
# This ended up being slower than just evaluating the function.
# Either bound could end up being the minimum. Check those too.
extrema = np.concatenate((extrema, bounds))
# Check every candidate by evaluating the polynomial at each possible minimum,
# and picking the minimum.
value_at_extrema = poly(extrema)
minimum_index = np.argmin(value_at_extrema)
return extrema[minimum_index]
# Warning: polynomial expects coeffients in the opposite order that you use.
poly = Polynomial([5,1,3,6,4])
print(find_minimum(poly, (-5, 5)))
這在我的計算機上需要 162 微秒,比 scipy.optimize 解決方案快大約 6 倍。 (問題中顯示的解決方案在我的計算機上需要 1.12 毫秒。)
這是一種更快的方法。 但是,它放棄了邊界檢查,使用了已棄用的 API,並且通常更難閱讀。
p = np.poly1d([4,6,3,1,5]) # Note: polynomials are opposite order of before
def find_minimum2(poly):
roots = np.real(np.roots(poly.deriv()))
return roots[np.argmin(poly(roots))]
print(find_minimum2(p))
它的時鍾速度為 110 微秒,比原來的速度快了大約 10 倍。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.