【发布时间】:2021-08-11 12:34:58
【问题描述】:
我希望使用我自己的目标函数而不是内置的正态最小二乘法对一些表格数据进行曲线拟合。
我可以使正常的 curve_fit 工作,但我不明白如何正确制定我的目标函数以将其输入到方法中。
我有兴趣了解我的拟合曲线在每个列表 x 值处的值。
x = np.array([-5.0,-4.5,-4.0,-3.5,-3.0,-2.5,-2.0,-1.5,-1.0,-0.5,0.0,0.5,1.0,1.5,2.0,2.5,3.0,3.5,4.0,4.5,5.0,5.5,6.0,6.5,7.0,7.5,8.0,8.5,9.0,9.5,10.0])
y = np.array([300,300,1000,350,340,1230,500,360,360,920,365,365,350,1000,375,1050,380,385,385,390,400,395,780,410,420,420,415,435,440,435,455])
e = np.array([math.sqrt(i) for i in y]) #uncertainty in y values
def test_func(x, a0, a1):
""" This is the function I want to fit to my data """
return a0 + a1*x
def norm_residual(test_func, x, y, e, params):
""" This calculates the normalised residuals, given the tabulated data and function parameters"""
yhat = test_func(x,*params)
z = (y-yhat)/e
return z
def f(z):
""" This modifies the normalised residual value, depending on it's sign."""
if z <= 0:
return z**2
else:
return 6*np.log(2*z/(np.sqrt(math.pi) * sp.special.erf(z/np.sqrt(2))))-3*np.log(2)
def objective(test_func, x, y, e, params):
"""This returns the sum of the modified normalised residuals. Smaller is better"""
z = norm_residual(test_func, x, y, e, params)
return np.sum(np.array([f(i) for i in z]))
#normal scipy curve fit
params, params_covariance = sp.optimize.curve_fit(test_func, x, y, p0=[0,0])
plt.scatter(x, y, label='Data')
plt.plot(x, test_func(x, params[0], params[1]), label='Fitted function', color="orange")
plt.legend(loc='best')
plt.show()
#how do I use my objective function to do my curve fit?
【问题讨论】:
-
以适用于数组的方式写入
f(z)。当前版本仅适用于标量值,因为if和math.. -
@hpaulj 我可以做到:
def f_mod(r): return np.array([f(i) for i in r]),但我该怎么办?它去哪儿了? optimize.curve_fit 文档说“优化的函数是chisq = sum((r / sigma) ** 2)”如何将其更改为chisq = sum(f_mod)?
标签: python numpy scipy scipy-optimize scipy-optimize-minimize