python - lmfit 不探索参数空间
问题描述
我正在尝试使用和类lmfit
为一些随机数据找到函数的最佳拟合参数。但是,它似乎并没有过多地探索参数空间。它会进行大约 10 次函数评估,然后返回一个非常合适的结果。Model
Parameters
这是代码:
import numpy as np
from lmfit.model import Model
from lmfit.parameter import Parameters
import matplotlib.pyplot as plt
def dip(x, loc, wid, dep):
"""Make a line with a dip in it"""
# Array of ones
y = np.ones_like(x)
# Define start and end points of dip
start = np.abs(x - (loc - (wid/2.))).argmin()
end = np.abs(x - (loc + (wid/2.))).argmin()
# Set depth of the dip
y[start:end] *= dep
return y
def fitter(x, loc, wid, dep, scatter=0.001, sigma=3):
"""Find the parameters of the dip function in random data"""
# Make the lmfit model
model = Model(dip)
# Make random data and print input values
rand_loc = abs(np.random.normal(loc, scale=0.02))
rand_wid = abs(np.random.normal(wid, scale=0.03))
rand_dep = abs(np.random.normal(dep, scale=0.005))
print('rand_loc: {}\nrand_wid: {}\nrand_dep: {}\n'.format(rand_loc, rand_wid, rand_dep))
data = dip(x, rand_loc, rand_wid, rand_dep) + np.random.normal(0, scatter, x.size)
# Make parameter ranges
params = Parameters()
params.add('loc', value=loc, min=x.min(), max=x.max())
params.add('wid', value=wid, min=0, max=x.max()-x.min())
params.add('dep', value=dep, min=scatter*10, max=0.8)
# Fit the data
result = model.fit(data, x=x, params)
print(result.fit_report())
# Plot it
plt.plot(x, data, 'bo')
plt.plot(x, result.init_fit, 'k--', label='initial fit')
plt.plot(x, result.best_fit, 'r-', label='best fit')
plt.legend(loc='best')
plt.show()
然后我运行:
fitter(np.linspace(55707.97, 55708.1, 100), loc=55708.02, wid=0.04, dep=0.98)
返回(例如,因为它是随机数据):
rand_loc: 55707.99659784677
rand_wid: 0.02015076619874132
rand_dep: 0.9849809461153651
[[Model]]
Model(dip)
[[Fit Statistics]]
# fitting method = leastsq
# function evals = 9
# data points = 100
# variables = 3
chi-square = 0.00336780
reduced chi-square = 3.4720e-05
Akaike info crit = -1023.86668
Bayesian info crit = -1016.05117
## Warning: uncertainties could not be estimated:
loc: at initial value
wid: at initial value
[[Variables]]
loc: 55708.0200 (init = 55708.02)
wid: 0.04000000 (init = 0.04)
dep: 0.99754082 (init = 0.98)
知道为什么它执行这么少的函数评估返回不合适吗?对此的任何帮助将不胜感激!
解决方案
这是一个与使用 scipy optimize curve_fit 拟合阶跃位置变化的阶跃函数类似的问题。请参阅https://stackoverflow.com/a/59504874/5179748。
基本上,求解器scipy.optimize/lmfit
假设参数是连续的——而不是离散的——变量。他们对参数进行小幅更改,以查看结果发生了什么变化。loc
和参数的微小变化wid
不会对结果产生影响,因为argmin()
总是会返回一个整数值。
您可能会发现使用有限宽度的矩形模型(请参阅https://lmfit.github.io/lmfit-py/builtin_models.html#rectanglemodel)会有所帮助。我稍微改变了你的例子,但这应该足以让你开始:
import numpy as np
import matplotlib.pyplot as plt
from lmfit.models import RectangleModel, ConstantModel
def dip(x, loc, wid, dep):
"""Make a line with a dip in it"""
# Array of ones
y = np.ones_like(x)
# Define start and end points of dip
start = np.abs(x - (loc - (wid/2.))).argmin()
end = np.abs(x - (loc + (wid/2.))).argmin()
# Set depth of the dip
y[start:end] *= dep
return y
x = np.linspace(0, 1, 201)
data = dip(x, 0.3, 0.09, 0.98) + np.random.normal(0, 0.001, x.size)
model = RectangleModel() + ConstantModel()
params = model.make_params(c=1.0, amplitude=-0.01, center1=.100, center2=0.7, sigma1=0.15)
params['sigma2'].expr = 'sigma1' # force left and right widths to be the same size
params['c'].vary = False # force offset = 1.0 : value away from "dip"
result = model.fit(data, params, x=x)
print(result.fit_report())
plt.plot(x, data, 'bo')
plt.plot(x, result.init_fit, 'k--', label='initial fit')
plt.plot(x, result.best_fit, 'r-', label='best fit')
plt.legend(loc='best')
plt.show()
推荐阅读
- tfs - TFS 2018:如何在任务板中设置限制?
- python - 如何在多天内处理来自多个来源的多个特征?
- c# - 解压缩 ZIP 流
- google-chrome - 最新的 Chrome 更新冻结了我的应用程序
- php - 在 PHP 中的 Docx 上添加行号
- javascript - 从 javascript/React.js 调用 python 分析库
- apache - proxypass后无法登录
- react-native - 反应原生的两个堆栈导航器
- sql - 出现错误“ORA-00933:SQL 命令未正确结束”
- google-apps-script - 如何授予 Apps Script Web App 授权以使用服务帐户为域中的所有用户访问 Google 表格