【问题标题】:Global fitting example with symfit带 symfit 的全局拟合示例
【发布时间】:2017-04-18 22:15:17
【问题描述】:

我正在尝试使用symfit 包执行全局拟合,遵循symfit documentation

import numpy as np
import symfit as sf
import matplotlib.pyplot as plt
%matplotlib inline # for ipynb

# Generate example data
t = np.arange(0.0, 600.1, 30)
k = 0.005
C1_0, C2_0 = 1.0, 2.0
C1 = C1_0 * np.exp(-k*t)
C2 = C2_0 * np.exp(-k*t)

# Construct model
x_1, x_2, y_1, y_2 = sf.variables('x_1, x_2, y_1, y_2')
kg = sf.Parameter(value=0.01, min=0.0, max=0.1)
a_1, a_2 = sf.parameters('a_1, a_2')
globalmodel = sf.Model({
    y_1: a_1 * np.e**(- kg * x_1),
    y_2: a_2 * np.e**(- kg * x_2),
})

# Do fit
globalfit = sf.Fit(globalmodel, x_1=t, x_2=t, y_1=C1, y_2=C2)
globalfit_result = globalfit.execute()
print(globalfit_result)

### EDITED START
while globalfit_result.r_squared < 0.99:
    kg = sf.Parameter(value=globalfit_result.params['kg'])
    a_1 = sf.Parameter(value=globalfit_result.params['a_1'])
    a_2 = sf.Parameter(value=globalfit_result.params['a_2'])
    globalmodel = sf.Model({
        y_1: a_1 * np.e**(- kg * x_1),
        y_2: a_2 * np.e**(- kg * x_2),
    })
    globalfit = sf.Fit(globalmodel, x_1=t, x_2=t, y_1=C1, y_2=C2)
    globalfit_result = globalfit.execute()
### EDITED END

y_r = globalmodel(x_1=t, x_2=t, **globalfit_result.params)

# Plot fit
plt.plot(t,C1,'ro')
plt.plot(t,C2,'b+')
plt.plot(t,y_r[0],'r-')
plt.plot(t,y_r[1],'b-')
plt.show()

在本例中,我希望“globalmodel”中的“kg”参数优化为 0.005。但是,“kg”的值约为 9.6e-3,与初始值(10.0e-3)太接近。我觉得我做了一些愚蠢的事情,但我想不通。

欢迎大家提出意见和建议!

已编辑

我添加了(一个非常丑陋的)while 循环以获得最佳匹配。我不知道为什么会这样,但它似乎有效。

【问题讨论】:

    标签: python curve-fitting symfit


    【解决方案1】:

    似乎是边界导致了问题。我在测试中删除了它们,然后一切正常。这是一个已知问题在symfit 0.3.3,和一个I已经固定在̶[̶̶m̶a̶s̶t̶e̶r̶̶]̶[1]̶BRANCH ON̶G̶i̶t̶h̶u̶b̶.̶̶̶我上传新的开发人员版你可以立即安装使用̶̶p̶i̶p̶ ̶i̶n̶s̶t̶a̶l̶l̶ ̶s̶y̶m̶f̶i̶t̶=̶=̶0̶.̶3̶.̶3̶.̶d̶e̶v̶1̶5̶5̶ ̶-̶-̶u̶p̶g̶r̶a̶d̶e̶̶,̶直到我正式发布0.3.4̶(这将是相同的,但具有扩展文档)̶,目前已被固定在较新版本。

    请注意,我将您的 np.e 更改为 sf.exp,因为那是象征性的。我的工作代码如下,除了提到并在0.3.3.dev155 中运行的更改之外,与您的相同。

    import numpy as np
    import symfit as sf
    import matplotlib.pyplot as plt
    
    # Generate example data
    t = np.arange(0.0, 600.1, 30)
    k = 0.005
    C1_0, C2_0 = 1.0, 2.0
    C1 = C1_0 * np.exp(-k*t)
    C2 = C2_0 * np.exp(-k*t)
    
    # Construct model
    x_1, x_2, y_1, y_2 = sf.variables('x_1, x_2, y_1, y_2')
    kg = sf.Parameter(value=0.01, min=0.0, max=0.1)
    a_1, a_2 = sf.parameters('a_1, a_2')
    globalmodel = sf.Model({
        y_1: a_1 * sf.exp(- kg * x_1),
        y_2: a_2 * sf.exp(- kg * x_2),
    })
    
    # Do fit
    globalfit = sf.Fit(globalmodel, x_1=t, x_2=t, y_1=C1, y_2=C2)
    globalfit_result = globalfit.execute()
    print(globalfit_result)
    
    y_r = globalmodel(x_1=t, x_2=t, **globalfit_result.params)
    
    # Plot fit
    plt.plot(t,C1,'ro')
    plt.plot(t,C2,'b+')
    plt.plot(t,y_r[0],'r-')
    plt.plot(t,y_r[1],'b-')
    plt.show()
    

    【讨论】:

    • 感谢您及时回复 0.3.3.dev155。除了下面的错误消息外,一切正常。 C:\Users\User\Miniconda2\lib\site-packages\scipy\optimize\slsqp.py:341:RuntimeWarning:在更大的 bnder 中遇到无效值 = where(bnds[:, 0] > bnds[:, 1]) [0] C:\Users\User\Miniconda2\lib\site-packages\symfit\core\fit.py:1610: FutureWarning: 与None 的比较将在未来进行元素对象比较。如果 self.sigma_data.values() 中没有:
    • 如果我理解正确,那是警告,对吧?所以你得到了正确的结果?我一定会在 0.3.4 中推出第二个 ;)。关于边界的警告更深,来自最小化算法,如果你仍然得到它,例如你把 min 改成小但非零的值?
    • 是的。我得到了正确的结果!两者都只是警告。即使我将“kg”的最小值更改为 0.001,第二个警告仍然存在。
    • 摆脱了它,现在发布了新版本,包括改进的文档;)
    • 附注如果我的回答解决了您的问题,您介意接受它作为答案吗? :)
    猜你喜欢
    • 2020-02-08
    • 1970-01-01
    • 2011-07-20
    • 2016-01-22
    • 2023-03-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多