object function可以return None带一定的参数,Curvefit收敛时如何跳过或避免?
Object function can return None with certain parameters, how to skip or avoid while converging in Curvefit?
在我的情况下,objective 函数是一个数值过程,包含一个通过二分法求方程根的过程。
对于某些参数集,方程没有中间变量的根。我认为制作二分求根例程 return 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
,显然不行。
我应该如何 return 来继续 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
到return最后一次尝试到a1
?
另一方面,当出现错误时,我尝试将对象函数中的 try... except...
设置为 return 0。
结果如我所料:
para,pvoc = sp.curve_fit(ff,x,y,p0=(-3,1))
#OptimizeWarning: Covariance of the parameters could not be estimated
category=OptimizeWarning)
我认为您想采取不同的方法。也就是说,您已将 objective 函数写入 return None
或 Inf
以在 a1
或 a2
的值超出范围时发出信号边界:a1<0
和 a2<0
不是 objective 函数可接受的值。
如果这是对您要执行的操作的正确解释,最好在 a1
和 a2
上设置界限,这样 objective 函数就永远不会得到那些价值观。要使用 curve_fit
做到这一点,您需要为下限和上限创建一个数组元组,其顺序与您的 p0
相匹配,因此
pout, pcov = sp.curve_fit(f, x, y, p0=(1, 1), bounds=([0, 0], [np.inpf, np.inf])
顺便说一句:我不知道您为什么要为 a1
使用小于 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
希望对您有所帮助。
在我的情况下,objective 函数是一个数值过程,包含一个通过二分法求方程根的过程。
对于某些参数集,方程没有中间变量的根。我认为制作二分求根例程 return 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
,显然不行。
我应该如何 return 来继续 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
到return最后一次尝试到a1
?
另一方面,当出现错误时,我尝试将对象函数中的 try... except...
设置为 return 0。
结果如我所料:
para,pvoc = sp.curve_fit(ff,x,y,p0=(-3,1))
#OptimizeWarning: Covariance of the parameters could not be estimated
category=OptimizeWarning)
我认为您想采取不同的方法。也就是说,您已将 objective 函数写入 return None
或 Inf
以在 a1
或 a2
的值超出范围时发出信号边界:a1<0
和 a2<0
不是 objective 函数可接受的值。
如果这是对您要执行的操作的正确解释,最好在 a1
和 a2
上设置界限,这样 objective 函数就永远不会得到那些价值观。要使用 curve_fit
做到这一点,您需要为下限和上限创建一个数组元组,其顺序与您的 p0
相匹配,因此
pout, pcov = sp.curve_fit(f, x, y, p0=(1, 1), bounds=([0, 0], [np.inpf, np.inf])
顺便说一句:我不知道您为什么要为 a1
使用小于 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
希望对您有所帮助。