lmfit 不适合 returns 单个标量值的简单示例中的唯一参数
lmfit does not fit the only parameter on a simple example that returns a single scalar value
残差函数 (res
) 计算 y>thr (threshold) 的 y 值之和。它 returns 此总和与目标之间的余数。
在这个例子中,target
是为 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
因为拟合试图找到 thr
应该改变的方式和程度。它会看到更改 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]
那个 step
数组将有 non-zero/non-one 接近阈值的值,为拟合提供足够的信号来决定移动到哪里。
此外,请注意,返回 [(target-sum)**2]
会起作用,但仅返回残差 target-sum
将使拟合不仅可以看到幅度,还可以看到失配的符号,并允许适合更快地收敛。
通过这些更改,您应该得到 thr
的正确值 70 以及大约 11 次函数评估。
残差函数 (res
) 计算 y>thr (threshold) 的 y 值之和。它 returns 此总和与目标之间的余数。
在这个例子中,target
是为 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
因为拟合试图找到 thr
应该改变的方式和程度。它会看到更改 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]
那个 step
数组将有 non-zero/non-one 接近阈值的值,为拟合提供足够的信号来决定移动到哪里。
此外,请注意,返回 [(target-sum)**2]
会起作用,但仅返回残差 target-sum
将使拟合不仅可以看到幅度,还可以看到失配的符号,并允许适合更快地收敛。
通过这些更改,您应该得到 thr
的正确值 70 以及大约 11 次函数评估。