如何使用 LMFIT 拟合具有共享参数的非线性曲线
How to fit non linear curve with shared parameters using LMFIT
我在 python 中使用 LMFIT 库制作曲线拟合程序时遇到了一些问题。
我的密码是
#Make spectrum
def df_one_row(n_si=1, k_si=1, level=0):
# Structure
layer_air = make_layer(nk_air)
layer_si = make_layer(n_si + 1j*k_si, thickness=0.05, coherence=False)
structure = [
layer_air,
layer_si,
layer_air]
R_S = Multilayer(structure, 0, 's', wavenumbers).R()
R_P = Multilayer(structure, 0, 'p', wavenumbers).R()
Ref=(R_S + R_P)/2
Ref += level/100
return Ref
def df_one_row1(n_si=1, k_si=1, level=0):
# Structure
layer_air = make_layer(nk_air)
layer_si = make_layer(n_si + 1j*k_si, thickness=0.05, coherence=False)
#layer_sio2_2 = make_layer(nk_sio2, thickness=d_sio2_2*1e-7, coherence=True)
structure = [
layer_air,
layer_si,
layer_air]
T_S = Multilayer(structure, 0, 's', wavenumbers).T()
T_P = Multilayer(structure, 0, 'p', wavenumbers).T()
Trans=(T_S + T_P)/2
Trans += level/100
return Trans
def epsilon(wavenumbers, w_0, w_p, gamma):
ep=(np.power(w_p,2)/((np.power(w_0,2)-np.power(wavenumbers,2))-(1j*gamma*wavenumbers)))
return ep
def refractive_index(wavenumbers, pars=1 ):
e_inf=pars['e_inf']
e= e_inf + epsilon( wavenumbers, pars['w_01'], pars['w_p1'], pars['gamma_1'] )
n=np.real(np.sqrt(e))
k=np.imag(np.sqrt(e))
return n,k
def residual(pars, x, sigma=None, data1=None, data2=None):
n,k=refractive_index(wavenumbers, pars)
parameter_list=[n,k]
model1=df_one_row(*parameter_list , level=pars['level'])
model2=df_one_row1(*parameter_list , level=pars['level'])
if data1 is None and data2 is None:
return model1, model2
if sigma is None:
return ((model1-data1)+(model2-data2))/2
return ((model1-data1)+(model2-data2))/2*sigma
pfit=lmfit.Parameters()
pfit.add_many( ('e_inf', 12., True,1.5, 20),
('w_01', 0.,False,1, 2000),
('w_p1', 10.,True,1, 1300),
('gamma_1',10, True, 1, 75),
('level',0,False, -8., 8.),
)
#Call Data
R=pd.read_csv('R_si.dat', sep='\t', header=None)
R=R.iloc[2:,1].to_numpy()
T=pd.read_csv('T_si.dat', sep='\t', header=None)
T=T.iloc[2:,1].to_numpy()
#Curve fit part
sigma=None
myfit = lmfit.minimize(residual, pfit, method='Least_squares', args=(wavenumbers,), kws=
{'sigma':sigma, 'data1': R, 'data2':T })
问题发生在
myfit = lmfit.minimize(residual, pfit, method='Least_squares', args=(wavenumbers,), kws=
{'sigma':sigma, 'data1': R, 'data2':T })
有这个错误
TypeError Traceback (most recent call last)
~\AppData\Local\Temp/ipykernel_15636/1802606526.py in <module>
1 sigma=None
----> 2 myfit = lmfit.minimize(residual, pfit, method='Least_squares', args=(wavenumbers,),
kws={'sigma':sigma, 'data1': R, 'data2':T })
~\anaconda3\lib\site-packages\lmfit\minimizer.py in minimize(fcn, params, method, args, kws,
iter_cb, scale_covar, nan_policy, reduce_fcn, calc_covar, max_nfev, **fit_kws)
2581 nan_policy=nan_policy, reduce_fcn=reduce_fcn,
2582 calc_covar=calc_covar, max_nfev=max_nfev, **fit_kws)
-> 2583 return fitter.minimize(method=method)
~\anaconda3\lib\site-packages\lmfit\minimizer.py in minimize(self, method, params, **kws)
2350 val.lower().startswith(user_method)):
2351 kwargs['method'] = val
-> 2352 return function(**kwargs)
2353
2354
~\anaconda3\lib\site-packages\lmfit\minimizer.py in least_squares(self, params, max_nfev,
**kws)
1572 result.call_kws = kws
1573 try:
-> 1574 ret = least_squares(self.__residual, start_vals,
1575 bounds=(lower_bounds, upper_bounds),
1576 kwargs=dict(apply_bounds_transformation=False),
~\anaconda3\lib\site-packages\scipy\optimize\_lsq\least_squares.py in least_squares(fun, x0,
jac, bounds, method, ftol, xtol, gtol, x_scale, loss, f_scale, diff_step, tr_solver,
tr_options, jac_sparsity, max_nfev, verbose, args, kwargs)
818 x0 = make_strictly_feasible(x0, lb, ub)
819
--> 820 f0 = fun_wrapped(x0)
821
822 if f0.ndim != 1:
~\anaconda3\lib\site-packages\scipy\optimize\_lsq\least_squares.py in fun_wrapped(x)
813
814 def fun_wrapped(x):
--> 815 return np.atleast_1d(fun(x, *args, **kwargs))
816
817 if method == 'trf':
~\anaconda3\lib\site-packages\lmfit\minimizer.py in __residual(self, fvars,
apply_bounds_transformation)
585 raise AbortFitException(f"fit aborted: too many function evaluations
{self.max_nfev}")
586
--> 587 out = self.userfcn(params, *self.userargs, **self.userkws)
588
589 if callable(self.iter_cb):
我的代码中相关的错误消息:
#主要错误
残差中的~\AppData\Local\Temp/ipykernel_15636/2292999671.py(pars, x, sigma, data1, data2)
---> 23 return ((model1-data1)+(model2-data2))/2
24 return ((model1-data1)+(model2-data2))/2*sigma
TypeError:- 的操作数类型不受支持:'float' 和 'str'
***
我还以为是kws的错误,不知道怎么改正。
我该怎么办?
错误信息
~\AppData\Local\Temp/ipykernel_15636/2292999671.py in residual(pars, x, sigma, data1, data2)
---> 23 return ((model1-data1)+(model2-data2))/2
24 return ((model1-data1)+(model2-data2))/2*sigma
TypeError: unsupported operand type(s) for -: 'float' and 'str' ***
表示 model1
、model2
、data1
和 data2
中的某些数据类型可能不是您假设的数据类型。
您没有提供足够的信息,无法了解像 df_one_row
这样的模型生成代码实际上 return.
我建议调试残差函数——用预期值调用它,并可能打印出中间结果以找出 TypeError 的来源。
我在 python 中使用 LMFIT 库制作曲线拟合程序时遇到了一些问题。
我的密码是
#Make spectrum
def df_one_row(n_si=1, k_si=1, level=0):
# Structure
layer_air = make_layer(nk_air)
layer_si = make_layer(n_si + 1j*k_si, thickness=0.05, coherence=False)
structure = [
layer_air,
layer_si,
layer_air]
R_S = Multilayer(structure, 0, 's', wavenumbers).R()
R_P = Multilayer(structure, 0, 'p', wavenumbers).R()
Ref=(R_S + R_P)/2
Ref += level/100
return Ref
def df_one_row1(n_si=1, k_si=1, level=0):
# Structure
layer_air = make_layer(nk_air)
layer_si = make_layer(n_si + 1j*k_si, thickness=0.05, coherence=False)
#layer_sio2_2 = make_layer(nk_sio2, thickness=d_sio2_2*1e-7, coherence=True)
structure = [
layer_air,
layer_si,
layer_air]
T_S = Multilayer(structure, 0, 's', wavenumbers).T()
T_P = Multilayer(structure, 0, 'p', wavenumbers).T()
Trans=(T_S + T_P)/2
Trans += level/100
return Trans
def epsilon(wavenumbers, w_0, w_p, gamma):
ep=(np.power(w_p,2)/((np.power(w_0,2)-np.power(wavenumbers,2))-(1j*gamma*wavenumbers)))
return ep
def refractive_index(wavenumbers, pars=1 ):
e_inf=pars['e_inf']
e= e_inf + epsilon( wavenumbers, pars['w_01'], pars['w_p1'], pars['gamma_1'] )
n=np.real(np.sqrt(e))
k=np.imag(np.sqrt(e))
return n,k
def residual(pars, x, sigma=None, data1=None, data2=None):
n,k=refractive_index(wavenumbers, pars)
parameter_list=[n,k]
model1=df_one_row(*parameter_list , level=pars['level'])
model2=df_one_row1(*parameter_list , level=pars['level'])
if data1 is None and data2 is None:
return model1, model2
if sigma is None:
return ((model1-data1)+(model2-data2))/2
return ((model1-data1)+(model2-data2))/2*sigma
pfit=lmfit.Parameters()
pfit.add_many( ('e_inf', 12., True,1.5, 20),
('w_01', 0.,False,1, 2000),
('w_p1', 10.,True,1, 1300),
('gamma_1',10, True, 1, 75),
('level',0,False, -8., 8.),
)
#Call Data
R=pd.read_csv('R_si.dat', sep='\t', header=None)
R=R.iloc[2:,1].to_numpy()
T=pd.read_csv('T_si.dat', sep='\t', header=None)
T=T.iloc[2:,1].to_numpy()
#Curve fit part
sigma=None
myfit = lmfit.minimize(residual, pfit, method='Least_squares', args=(wavenumbers,), kws=
{'sigma':sigma, 'data1': R, 'data2':T })
问题发生在
myfit = lmfit.minimize(residual, pfit, method='Least_squares', args=(wavenumbers,), kws=
{'sigma':sigma, 'data1': R, 'data2':T })
有这个错误
TypeError Traceback (most recent call last)
~\AppData\Local\Temp/ipykernel_15636/1802606526.py in <module>
1 sigma=None
----> 2 myfit = lmfit.minimize(residual, pfit, method='Least_squares', args=(wavenumbers,),
kws={'sigma':sigma, 'data1': R, 'data2':T })
~\anaconda3\lib\site-packages\lmfit\minimizer.py in minimize(fcn, params, method, args, kws,
iter_cb, scale_covar, nan_policy, reduce_fcn, calc_covar, max_nfev, **fit_kws)
2581 nan_policy=nan_policy, reduce_fcn=reduce_fcn,
2582 calc_covar=calc_covar, max_nfev=max_nfev, **fit_kws)
-> 2583 return fitter.minimize(method=method)
~\anaconda3\lib\site-packages\lmfit\minimizer.py in minimize(self, method, params, **kws)
2350 val.lower().startswith(user_method)):
2351 kwargs['method'] = val
-> 2352 return function(**kwargs)
2353
2354
~\anaconda3\lib\site-packages\lmfit\minimizer.py in least_squares(self, params, max_nfev,
**kws)
1572 result.call_kws = kws
1573 try:
-> 1574 ret = least_squares(self.__residual, start_vals,
1575 bounds=(lower_bounds, upper_bounds),
1576 kwargs=dict(apply_bounds_transformation=False),
~\anaconda3\lib\site-packages\scipy\optimize\_lsq\least_squares.py in least_squares(fun, x0,
jac, bounds, method, ftol, xtol, gtol, x_scale, loss, f_scale, diff_step, tr_solver,
tr_options, jac_sparsity, max_nfev, verbose, args, kwargs)
818 x0 = make_strictly_feasible(x0, lb, ub)
819
--> 820 f0 = fun_wrapped(x0)
821
822 if f0.ndim != 1:
~\anaconda3\lib\site-packages\scipy\optimize\_lsq\least_squares.py in fun_wrapped(x)
813
814 def fun_wrapped(x):
--> 815 return np.atleast_1d(fun(x, *args, **kwargs))
816
817 if method == 'trf':
~\anaconda3\lib\site-packages\lmfit\minimizer.py in __residual(self, fvars,
apply_bounds_transformation)
585 raise AbortFitException(f"fit aborted: too many function evaluations
{self.max_nfev}")
586
--> 587 out = self.userfcn(params, *self.userargs, **self.userkws)
588
589 if callable(self.iter_cb):
我的代码中相关的错误消息:
#主要错误
残差中的~\AppData\Local\Temp/ipykernel_15636/2292999671.py(pars, x, sigma, data1, data2)
---> 23 return ((model1-data1)+(model2-data2))/2
24 return ((model1-data1)+(model2-data2))/2*sigma
TypeError:- 的操作数类型不受支持:'float' 和 'str'
***
我还以为是kws的错误,不知道怎么改正。
我该怎么办?
错误信息
~\AppData\Local\Temp/ipykernel_15636/2292999671.py in residual(pars, x, sigma, data1, data2)
---> 23 return ((model1-data1)+(model2-data2))/2
24 return ((model1-data1)+(model2-data2))/2*sigma
TypeError: unsupported operand type(s) for -: 'float' and 'str' ***
表示 model1
、model2
、data1
和 data2
中的某些数据类型可能不是您假设的数据类型。
您没有提供足够的信息,无法了解像 df_one_row
这样的模型生成代码实际上 return.
我建议调试残差函数——用预期值调用它,并可能打印出中间结果以找出 TypeError 的来源。