lmfit并最小化多个数据集的功能

时间:2017-10-03 08:50:17

标签: python least-squares lmfit

我的脚本问题用于同时描述一组带有一些常见参数的数据。该计划相当漫长而复杂,为了简单起见,我在这里报告了必要的部分。本文末尾提供完整的脚本和一组数据。

在第一步中,我导入要安装的数据。 qexp是我的自变量的值,RRexp是我要建模的实验数据。 RRerr是他们的不确定性,qres是我的自变量的不确定性(这里没有使用)。

data = []
Files = ['LC-VoS-2.4-00.mft', 'LC-VoS-2.4-10.mft', 'LC-VoS-2.4-30.mft', 'LC-VoS-2.4-50.mft'] #, 'LC-VoS-2.3-65.mft']
for i in range(len(Files)):
  qexp, RRexp, RRerr, qres = np.loadtxt(Files[i], unpack=True, skiprows=23, usecols=(0,1,2,3))
  dataset = np.zeros(shape=(len(qexp),5))
  dataset[:,0:4] = np.column_stack((qexp*10, RRexp, RRerr, qres*10))
  data.append(dataset)

我定义了计算理论曲线所需的所有参数(我只展示其中一些参数):

fit_params = Parameters()
#Parameters valid for each humidity series, values guessed  
fit_params.add('N', value = 3.85 , min = 1.0, max = 15.0, vary=True) 
fit_params.add('dd_alk', value = 0.80, min = 0.4, max = 2.5, vary=True) 
...
for i in range(len(Files)):
fit_params.add_many(('sig_l' + str(i), 0.15, False, 0.0, None),   
                    ('sig_N' + str(i), 0.3, False, 0.0,  None))

此函数将残差返回给f2min_inc函数,由最小值调用。 data1和data2由calcRR函数计算,使用数据数组中包含的x值(qexp),SLDx数组和GFP []中包含的一些参数。计算值存储在数据[:] [:,4]中。

def Resid_inc(Files,SLD1,SLD2,data,GFP): #Function calculates the residuum for the fit. 
  res = []
  data1 = CalcRR(data, SLD1, GFP)
  data2 = CalcRR(data, SLD2, GFP)
  for i in range(len(Files)):
        data[i][:,4] = data1[i][:,4]*(1.0-fit_params['N'].value+int(fit_params['N'].value))+data2[i][:,4]*(fit_params['N'].value-int(fit_params['N'].value))
  for i in range(len(Files)):
    linres = (data[i][:,1]-data[i][:,4])/data[i][:,2]
    res = np.append(res, linres)
  return res

这是一个中间函数(可以跳过),由最小化函数调用,返回残差。在第一行中,基于fit_parameters计算四个阵列Phi_s1,Phi_s2,SLD1和SLD2。需要这些数组来计算理论曲线,这在Resid_inc函数中完成。

def f2min_inc(fit_params):
  Phi_s1, Phi_s2, SLD1, SLD2 = nr.Par(fit_params, Files, GFP, coher)
  res = Resid_inc(Files,SLD1,SLD2,data,GFP)
  return res

这里我称之为lmfit最小化功能。     out =最小化(f2min_inc,fit_params,iter_cb = printout,method ='leastsq')

虽然我没有在最小化中定义args,但软件运行顺畅,没有出现错误消息,拟合过程运行一段时间然后结束。但是,参数的变化很小,并且返回时没有标准偏差。该报告如下:

[[Fit Statistics]]
    # function evals   = 103
    # data points      = 1193
    # variables        = 4
    chi-square         = 290351.201
    reduced chi-square = 244.198
[[Variables]]
    N:            3.85000000 +/- 0        (0.00%) (init= 3.85)
    dd_alk:       0.80196356 +/- 0        (0.00%) (init= 0.8)
    dd_eo:        0.40098178 +/- 0        (0.00%)  == 'dd_alk*0.34/0.34/2.'
    dd_ch:        2.09873200 +/- 0        (0.00%) (init= 2.1)
    dd_ch0:       1.49802709 +/- 0        (0.00%) (init= 1.5)
    dd_ch_last:   0.5 (fixed)
    dd_SiO2:      2.3 (fixed)
    sig_Si:       0.2 (fixed)
    sig_SiO2:     0.25 (fixed)
    a:            0 (fixed)
    b:            0          +/- 0          == 'a'
    sig_l0:       1 (fixed)
    sig_N0:       0.05 (fixed)
    f_eo0:        0 (fixed)
    f_ch0:        0 (fixed)
    f_ch00:       0 (fixed)
    f_holech0:    0.45 (fixed)
    f_holeo0:     0.45000000 +/- 0        (0.00%)  == 'f_holech0'
    sig_l1:       1 (fixed)
    sig_N1:       0.1 (fixed)
    f_eo1:        0.1 (fixed)
    f_ch1:        0.05 (fixed)
    f_ch01:       0.05 (fixed)
    f_holech1:    0 (fixed)
    f_holeo1:     0 (fixed)
    sig_l2:       1 (fixed)
    sig_N2:       0.08 (fixed)
    f_eo2:        0.2 (fixed)
    f_ch2:        0.15 (fixed)
    f_ch02:       0.15 (fixed)
    f_holech2:    0 (fixed)
    f_holeo2:     0 (fixed)
    sig_l3:       1 (fixed)
    sig_N3:       0.08 (fixed)
    f_eo3:        0.5 (fixed)
    f_ch3:        0.28 (fixed)
    f_ch03:       0.42 (fixed)
    f_holech3:    0 (fixed)
    f_holeo3:     0 (fixed)

正如你所看到的,参数略有改变,但微不足道。我认为这可能会出现在模型的复杂性上。但是,即使我尝试最小化一个参数,问题仍然存在。此外,通过改变最小化算法对输出没有影响,输出始终非常接近猜测的参数。我也很确定,我没有达到最低限度,因为我可以通过更改初始参数来获得更好的猜测。

我担心问题在于我如何编写脚本,即使我无法识别任何明显的问题(但我的编程技巧非常有限)。

可以在此处下载包含一组数据的完整脚本: https://tubcloud.tu-berlin.de/s/4oUzu6d5Mvwczle

提前感谢您的意见。

1 个答案:

答案 0 :(得分:0)

将问题简化为最简单,最简单的示例总是有帮助的。有一个复杂的例子,有太多的地方需要检查。可以肯定的是,lmfit可以处理具有许多参数和复杂功能的复杂示例,但您必须从简单版本构建这些示例或测试不同的组件。

并且,如果您不包含完整代码(例如nr.Par(),这是适合参数发送的位置),您希望我们如何知道代码在做什么?我们只能猜测 - 您为什么要求帮助并故意不提供您所拥有的所有信息?

好的,还有:Resid_inc使用fit_params['N']。这是从哪里来的?您是否期望它会使用拟合参数?

由于您的参数N在拟合中完全没有变化(甚至没有变化),并且由于您在fit_params['N']中使用Resid_inc而没有将其传入,我会冒险猜测:

  1. Resid_inc是您使用参数N的唯一值的地方。

  2. 您误以为fit_params传入您的f2min_inc将是Resid_inc中使用的f2min_inc。事实上,他们不会。在每次调用中,lmfit.Parameters将获得一个fit_params,其中包含更新的值,这些值将放入函数f2min_inc内(和本地)的minimize()对象中。外部模块代码中的值以及传入fit_params的值也恰好被命名为fit_params,但这不是同一个对象,这些值不会被更改

  3. 简而言之,我认为您希望将Resid_inc传递给interface Store { name: string, age: number } interface Setter<K extends keyof T, T = Store> { type: 'SET_VALUE', field: K value: T[K] } const validName: Setter<'name'> = { type: 'SET_VALUE', field: 'name', value: 'thename', } const validAge: Setter<'age'> = { type: 'SET_VALUE', field: 'age', value: 30, } 函数。