0

我对用于同时描述具有一些常见参数的一组数据的脚本有疑问。该程序相当长且复杂,为了简单起见,我在这里报告基本部分。本文末尾提供了完整的脚本和一组数据。

第一步,我导入要拟合的数据。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[] 中包含的一些参数。计算值存储在 data[:][:,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,方法='leastsq')

虽然我没有在minimize中定义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

提前感谢您的评论。

4

1 回答 1

0

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

而且,如果您不包含完整的代码(例如nr.Par(),发送 fit 参数的位置),您如何期望我们知道代码在做什么?我们只能猜测——你为什么要寻求帮助,却故意不提供所有可用的信息?

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

由于您的参数N在合适的情况下根本没有改变(甚至没有改变),并且由于您fit_params['N']Resid_inc没有传递它的情况下使用 in ,所以我会冒险猜测:

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

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

简而言之,我认为您想传递fit_params给您的Resid_inc功能。

于 2017-10-04T02:24:17.383 回答