简体   繁体   English

lmfit:如何通过在LMFIT中的其他参数之间限制它来对一个参数添加约束?

[英]lmfit: how to add a constraint on a parameter by bounding it between other parameters in LMFIT?

I have a function for fitting: 我有一个拟合函数:

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()

As you can see, the parameter "ci" has to be bounded between other parameters. 如您所见,参数“ ci”必须限制在其他参数之间。 I put my constraints in an if statement; 我将约束放在if语句中; however, I got an error that name 'ci' is not defined. 但是,我收到一个未定义名称“ ci”的错误。 I think the reason is that I put the ci in two inequalities with other parameters. 我认为原因是我将ci置于其他参数不相等的两个不等式中。 How can I tell my code that I want "ci" to be bounded? 我如何告诉我的代码我希望“ ci”是有界的? (with the bound that I've shown now in my code) (与我现在在代码中显示的边界)

There are a number of odd things happening here that set off alarm bells and that you should probably fix: 这里发生了许多奇怪的事情,这些事情引起了警钟,您可能应该修复:

Zeroth, don't name a parameter 'pi'. 零,不要将参数命名为“ pi”。 Code is meant to be read and that's just going to mess with people's minds. 代码应该被阅读,这只会使人们的思想混乱。 Below, I will call this 'phi'. 在下面,我将其称为“ phi”。

First, the initial values for your parameters do not need 15 significant digits. 首先,参数的初始值不需要15个有效数字。

Second, be careful to avoid variables with values that differ in scale by many orders of magnitude. 其次,要小心避免变量值的大小相差很多数量级。 if 'pr' is expected to be ~3e8 and 'phi' is expected to be ~9e9, consider "changing units" by 1e6 or 1e9 so that variable values are closer to unity. 如果“ pr”预计为〜3e8,而“ phi”预期为〜9e9,请考虑“以1e6或1e9更改单位”,以使变量值更接近于1。

OK, on to the actual question. 好的,关于实际问题。 I would try this: 我会尝试这样的:

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)')

Now, as xangle varies between -pi/2 and +pi/2 , ci will be able to take any value that is between -cr*pr/phi and +cr*pr/phi . 现在,由于xangle-pi/2+pi/2之间变化,因此ci可以采用介于-cr*pr/phi+cr*pr/phi之间的任何值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM