对v4.0中建模的更改

为了减少内部代码的复杂程度,提高性能,并使复合模型中参数的行为更直观,在内部对建模代码进行了许多更改,特别是对复合模型和参数进行了修改。本页总结了重要的变化。更多的技术细节在最后给出,但一般不必阅读这些,除非你想了解为什么有些改变是必要的。

  • 已删除对建模类表达式的支持。仍然完全支持模型类实例的表达式。这样做是为了简化实现,提高性能,并支持新的参数语义。例如:

    不再工作:

    NewCompoundClass = Gaussian1D + Const1D
    

    仍然有效:

    newmodel = Gaussian1D(3.2, 7.1, 2.1) + Const1D(3.)
    
  • 在v4.0之前,参数是类描述符,这意味着它们不能保存模型的值。相反,这些值被保存在模型中。这导致在使用复合模型时出现混乱,因为这需要复合模型复制值。因此,改变复合模型中的值不会改变组成模型的参数值,反之亦然。现在参数对于每个用途都是不同的实例,它们确实保存了参数的值,因此复合模型现在与组成模型共享相同的值。

  • 以前使用模型集时,参数形状没有显示模型数量的相应维度。现在是了。例如:

    陈旧::

    In [1]: g = Gaussian1D([1,1], [1,2], [2,4], n_models=2)
    In [2]: g.amplitude
    Out[2]: Parameter('amplitude', value=[1. 1.])
    In [3]: g.amplitude.shape
    Out[3]: ()
    

    新::

    In [1]: g = Gaussian1D([1,1], [1,2], [2,4], n_models=2)
    In [2]: g.amplitude
    Out[2]: Parameter('amplitude', value=[1. 1.])
    In [3]: g.amplitude.shape
    Out[3]: (2,)
    
  • 以前,值保存在模型实例中的一个数组中,可以将值分配给该数组的切片。重新指派阵列确实会更新参数,但指派切片则不会。新方法要么通过赋值给parameters属性来替换整个数组,要么直接赋值给parameters值。

  • “插补”单位的使用,即在没有输入/输出单位的情况下向复合模型提供输入/输出单位,但部件模型支持 _parameter_units_for_data_units() 方法的适用性受到更多限制,只有当复合表达式使用 +- 操作员。过去的行为有时会导致单位的任意分配,有时还会导致参数的单位不正确。

  • 切片现在限制更大了。以前定义为这样的模型:

    m = m1 * m2 + m3
    

    允许此切片:

    m[1:] # results in m2 + m3
    

    现在,只允许表达式树中的子模型(将其视为执行的操作序列)作为切片。这意味着一些有意义的片段现在不起作用了。下面的代码说明了什么是允许的,什么是不允许的:

    m = m1 + m2 + m3 + m4
    m[:2] # Results in m1 + m2, works
    m[1:] # Should result in m2 + m3 + m4, does not work
           # since m1 is part of all subexpressions.
    
  • 一般来说,所有的公共方法都没有改变。例外情况是 n_submodels 以前是方法,现在是属性。

  • 许多非公开的方法都发生了变化,特别是对于复合模型。

  • 这个 _CompoundModelMeta 元类不再存在。

技术细节

复合模型实现更改

以前,复合模型是使用复合模型的元类实现的,同时也继承了模型类(它本身有一个元类)。这种方法的主要原因是支持模型类的表达式。然而,当模型类的表达式也包含模型实例时,这会导致一个令人困惑的实现,一些性能下降,以及一些奇怪的结果。

新的实现去掉了复合模型的元类,相应地不再支持模型类的表达式,而只支持模型实例的表达式。以前表达式树是私有属性。现在复合类本身就是一个表达式树。

复合模型的许多私有方法已经改变。