【问题标题】:lmfit: how to add a constraint on a parameter by bounding it between other parameters in LMFIT?lmfit:如何通过在 LMFIT 中的其他参数之间限制参数来添加对参数的约束?
【发布时间】:2019-12-18 15:29:40
【问题描述】:

我有一个拟合函数:

import cvxpy as cp
import numpy as np
from scipy.optimize import minimize
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
from lmfit import Model, Parameters




def f(wdata, pr, pi, cr, ci):
    return (  np.arctan2(-2*ci*pi - 2*cr*pr, 2*cr*wdata) - np.arctan2((pi)**2 + (pr)**2 - (wdata)**2, -2*pr*wdata)  )

wdata = (500000000.0, 520000000.0, 540000000.0, 560000000.0, 580000000.0, 600000000.0, 620000000.0, 640000000.0, 660000000.0, 680000000.0, 700000000.0, 720000000.0, 740000000.0, 760000000.0])

wdata= np.asarray(wdata)
ydata = f(wdata, -355574682.231318, -9040912422.93189, 31570159.4732856, -6238484.15663787)

fmodel = Model(f)
params = Parameters()
params.add('pr', value=-355574682.231318, vary=True)
params.add('pi', value=-9040912422.93189, vary=True)
params.add('pi', value=-9040912422.93189, vary=True)
params.add('cr', value=31570159.4732856, vary=True)

params.add('ci', expr='-((cr*pr)/pi) < ci < (cr*pr)/pi if pi<0 else ((cr*pr)/pi) < ci < -(cr*pr)/pi ', vary=True)




result = fmodel.fit(ydata, params, wdata=wdata)
print(result.fit_report())

plt.plot(wdata, ydata, 'bo')
plt.plot(wdata, result.init_fit, 'k--')
plt.plot(wdata, result.best_fit, 'r-')
plt.show()

如您所见,参数“ci”必须在其他参数之间进行限制。我将约束放在 if 语句中;但是,我收到一个错误,即未定义名称“ci”。我认为原因是我将 ci 与其他参数放在了两个不等式中。如何告诉我的代码我希望“ci”有界? (与我现在在我的代码中显示的界限)

【问题讨论】:

    标签: python optimization scipy curve-fitting lmfit


    【解决方案1】:

    这里发生了许多奇怪的事情,引发了警钟,你应该解决这些问题:

    Zeroth,不要将参数命名为“pi”。代码是用来阅读的,它只会扰乱人们的思想。下面,我将其称为“phi”。

    首先,参数的初始值不需要 15 位有效数字。

    其次,要小心避免变量值在尺度上相差多个数量级。如果 'pr' 预计为 ~3e8 并且 'phi' 预计为 ~9e9,请考虑通过 1e6 或 1e9 “更改单位”,以使变量值更接近统一。

    好的,进入实际问题。我会试试这个:

    params.add('pr', value=-3.6e8, vary=True)
    params.add('phi', value=-9.0e9, vary=True)
    params.add('cr', value=3.2e7, vary=True)
    
    # add a new *internal* variable that is bound on [-pi/2, pi/2]
    params.add('xangle', value=0.05, vary=True, min=-np.pi/2, max=np.pi/2)
    
    # constrain 'ci' to be '(cr*pr/phi)*sin(xangle)'
    params.add('ci', expr='(cr*pr/phi)*sin(xangle)')
    

    现在,由于 xangle-pi/2+pi/2 之间变化,ci 将能够采用介于 -cr*pr/phi+cr*pr/phi 之间的任何值。

    【讨论】:

    • 非常感谢您富有洞察力的 cmets。实际上,那个变量是我的极点的虚部,所以我把它作为 Pi。我还有一个问题,是否可以添加另一条曲线,并以优化变量的方式更改代码以同时最适合两条曲线。
    • 那么一定要把变量名改成Pole_realPole_imag——其他人(包括你,六个月后!)更容易理解。在评论中回答不同的问题(或在 SO 概念中)实际上是不可能的:问另一个问题。 FWIW,连接两个残差数组是拟合多个数据集的正常方法,因此“只”为连接数据集编写一个模型。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-20
    • 2020-08-18
    • 1970-01-01
    • 1970-01-01
    • 2020-04-21
    • 1970-01-01
    相关资源
    最近更新 更多