如何使用 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' ***

表示 model1model2data1data2 中的某些数据类型可能不是您假设的数据类型。

您没有提供足够的信息,无法了解像 df_one_row 这样的模型生成代码实际上 return.

我建议调试残差函数——用预期值调用它,并可能打印出中间结果以找出 TypeError 的来源。