在我的情况下,目标函数是一个数值过程,包含通过二分法的方程的根查找过程。
对于某些参数集,该等式没有中间变量的根。我认为使二分根发现例程返回None
可以解决这个问题。
由于对象函数的一组日期由scipy.optimize.curve_fit
和p0
进行回归,其间由此情况分隔,因此错误将停止该过程。
为了研究这个案例,我们展示了一个简化的案例。
import numpy as np
#Define object function:
def f(x,a1,a2):
if a1 < 0:
return None
elif a2 < 0:
return np.inf
else:
return a1 * x**2 + a2
#Making data:
x = np.linspace(-5,5,10)
i = 0
y = np.empty_like(x)
for xi in x:
y[i] = f(xi,1,1)
i += 1
import scipy.optimize as sp
para,pvoc = sp.curve_fit(f,x,y,p0=(-1,1))
#TypeError: unsupported operand type(s) for -: 'NoneType' and 'float'
para,pvoc = sp.curve_fit(f,x,y,p0=(1,-1))
#RuntimeError: Optimal parameters not found: Number of calls to function has reached maxfev = 600.
我也试过inf
,但显然不行。
我应该返回什么才能继续curve_fit
进程?
想象一下,它正试图收敛,curve_fit
遇到这种情况时会发生什么。
额外的想法:
我尝试try...except...
忽略错误,并模拟p0
处于可解决范围内的情况,但会将无法解析的段传递给真正的拟合。
import numpy as np
def f(x,a1,a2):
if a1 < 0:
return None
elif a1 < 2:
return a1 * x**2 + a2
elif a2 < 0:
return np.inf
else:
return a1 * x**2 + a2
def ff(x,a1,a2):
output = f(x,a1,a2)
if output == None:
return 0
else:
return output
x = np.linspace(-5,5,10)
i = 0
y = np.empty_like(x)
for xi in x:
y[i] = f(xi,1,1)
i += 1
import scipy.optimize as sp
#para,pvoc = sp.curve_fit(f,x,y,p0=(-1,1))
#TypeError: unsupported operand type(s) for -: 'NoneType' and 'float':
#para,pvoc = sp.curve_fit(f,x,y,p0=(1,-1))
try:
para,pvoc = sp.curve_fit(f,x,y,p0=(-3,1))
except TypeError:
pass
显然在融合过程中遇到了错误,并且已被报告并被排除在外。
如何继续curve_fit
原始收敛方向?
即使我可以让步,我如何告诉curve_fit
将最后一次尝试返回a1
?
另一方面,我尝试将此try... except...
置于对象函数中,以便在出现错误时返回0。
结果就像我期望的那样:
para,pvoc = sp.curve_fit(ff,x,y,p0=(-3,1))
#OptimizeWarning: Covariance of the parameters could not be estimated
category=OptimizeWarning)
答案 0 :(得分:0)
我认为你想采取不同的方法。也就是说,您已编写目标函数以返回None
或Inf
,以便在a1
或a2
的值超出范围时发出信号:a1<0
并且a2<0
不是目标函数的可接受值。
如果这是对您要做的事情的正确解释,最好在a1
和a2
上放置边界,以便目标函数永远不会获得这些值。要使用curve_fit
执行此操作,您需要为下限和上限创建一个数组元组,其顺序与p0
匹配,因此
pout, pcov = sp.curve_fit(f, x, y, p0=(1, 1), bounds=([0, 0], [np.inpf, np.inf])
顺便说一句:我不知道为什么你使用的a1
的起始值是&lt; 0,等超出范围。这似乎是你在寻找麻烦。
为了更好地设置拟合参数的界限,您可以考虑使用lmfit
,这将允许您编写:
import numpy as np
from lmfit import Model
def f(x, a1, a2):
return a1 * x**2 + a2
fmod = Model(f)
params = fmod.make_params(a1=1, a2=0.5)
params['a1'].min = 0
params['a2'].min = 0
x = np.linspace(-5, 5, 10)
np.random.seed(0)
y = f(x, 1, 1) + np.random.normal(size=len(x), scale=0.02)
result = fmod.fit(y, params, x=x)
print(result.fit_report())
将打印出来
[[Model]]
Model(f)
[[Fit Statistics]]
# fitting method = leastsq
# function evals = 13
# data points = 10
# variables = 2
chi-square = 0.00374066
reduced chi-square = 4.6758e-04
Akaike info crit = -74.9107853
Bayesian info crit = -74.3056151
[[Variables]]
a1: 0.99998038 +/- 7.6225e-04 (0.08%) (init = 1)
a2: 1.01496025 +/- 0.01034565 (1.02%) (init = 0.5)
[[Correlations]] (unreported correlations are < 0.100)
C(a1, a2) = -0.750
希望有所帮助。