Python lmfit并不是返回单个标量值的简单示例上的唯一参数
剩余函数(Python lmfit并不是返回单个标量值的简单示例上的唯一参数,python,numpy,scipy-optimize,lmfit,Python,Numpy,Scipy Optimize,Lmfit,剩余函数(res)计算y>thr的y值之和(阈值)。它返回此和与目标之间的剩余值 在本例中,计算y>70的目标,我希望在最小化后,从y=60开始计算y=70 import numpy as np import lmfit x=np.linspace(0,10,51) y=(x+4)*(x-14)*-1 def res(params,y,target): parvals = params.valuesdict() sum=y[y>parvals['thr']].sum()
res
)计算y>thr的y值之和(阈值)。它返回此和与目标之间的剩余值
在本例中,计算y>70的目标,我希望在最小化后,从y=60开始计算y=70
import numpy as np
import lmfit
x=np.linspace(0,10,51)
y=(x+4)*(x-14)*-1
def res(params,y,target):
parvals = params.valuesdict()
sum=y[y>parvals['thr']].sum()
return [(target-sum)**2]
target=y[y>70].sum()
pars=lmfit.Parameters()
pars.add('thr', value=60, min=y.min(), max=y.max())
minner = lmfit.Minimizer(res, pars, fcn_args=(y, target))
result = minner.minimize()
为什么拟合不起作用:不返回70,但返回60(初始值)
谢谢您的回答。拟合不起作用,因为您使用了连续变量(pars['thr']
)作为离散值[y>parvals['thr']]
。运行拟合时,它将尝试通过对变量值进行微小更改来计算结果中的变化。
如果在函数中添加print()
:
def res(params,y,target):
parvals = params.valuesdict()
print(parvals['thr'])
sum=y[y>parvals['thr']].sum()
return [(target-sum)**2]
你会得到
60.0
60.0
60.0
60.00000089406967
60.0
当fit试图找到应该改变的方式和幅度时。它将看到更改thr
对结果没有影响
基本上,您需要将thr
的用法从离散变量更改为连续变量。一个简单的方法是使用erf
函数(或另一个sigmoidal函数),例如,在一个小但不是无限小的间隔内从~0缩放到~1
from scipy.special import erf
def res(params,y,target):
parvals = params.valuesdict()
step = (1 + erf(y-parvals['thr']))/2.0
sum = (y*step).sum()
return target-sum # was [(target-sum)**2]
该步骤
数组将在阈值附近具有非零/非一值,为拟合提供足够的信号,以决定移动到哪里
另外,请注意,返回[(目标和)**2]
将起作用,但仅返回残差目标和将允许拟合不仅可以看到失配的幅度,还可以看到失配的符号,并允许拟合更快地收敛
通过这些更改,您应该获得70的thr
的正确值,并进行大约11次功能评估。@M Newville。我注意到不连续性是问题所在。所以,我打算问一个新问题,但你以前回答过。非常感谢您的解决方案。