python - 如何确定使用 lmfit 进行曲线拟合的初始参数值
问题描述
我目前正在对来自 DMA 测试(流变学)的几个数据进行非线性拟合。对于我目前正在使用的数据,该程序可以工作,但我希望程序能够灵活地使曲线拟合的起始参数取决于我的数据输入。有没有办法确定这一点?
也许是蒙特卡洛方法,但我不知道从哪里开始。
这是我的代码,提前谢谢!:
def calc_gmm(dframe):
array_omega = np.array(dframe['Angular Frequency']).flatten()
array_G_storage = np.array(dframe['Storage Modulus']).flatten()
array_G_loss = np.array(dframe['Loss Modulus']).flatten()
chisqr = 99999999999;
j=1
fig, (ax1,ax2) = plt.subplots(nrows=2, ncols=1)
while j <= 10:
params = lmfit.Parameters()
# Adding amount n of parameters and G0, start values were determined by trial and error
params.add('n', value=j, vary=False, min=1, max=10)
params.add('G0', value=0.4, min=0)
for i in range(params['n'].value):
params.add(f't_{i}', value=0.5, min=0)
params.add(f'g_{i}', value=17, min=0)
# Minimization function
res = lmfit.minimize(min_function, params, args=(array_omega, array_G_storage, array_G_loss))
# Determining the smallest chi-squared in order to develop a criterium to stop iterating over different orders
if res.chisqr < chisqr*0.5:
chisqr = res.chisqr
ax1.plot(array_omega, array_G_storage + res.residual, label='n: '+ (str)(j))
ax2.plot(array_omega, array_G_loss + res.residual, label='n: '+ (str)(j))
j += 1
else:
params = lmfit.Parameters()
j -= 1
# Adding amount n of parameters and G0, start values were determined by trial and error
params.add('n', value=j, vary=False, min=1, max=10)
params.add('G0', value=0.4, min=0)
for i in range(params['n'].value):
params.add(f't_{i}', value=0.5, min=0)
params.add(f'g_{i}', value=17, min=0)
# Minimization function
res = lmfit.minimize(min_function, params, args=(array_omega, array_G_storage, array_G_loss))
j = 11
解决方案
一般来说,答案是“否”——参数值的适当范围将取决于目标函数对参数的作用。就像,为了清楚起见,它可以首先将所有 't_N' 参数乘以 1e-6。用户需要知道函数将如何处理参数。由于您确实在拟合实验数据,因此您可以(例如)断言参数的单位是什么。
但是,如果你有一个稳定的函数定义和一些单位或参数的明确定义,你也许可以想出一套不错的起始参数。
对于 lmfit 中的许多模型函数(请参阅https://github.com/lmfit/lmfit-py/blob/master/lmfit/models.py),我们可以对一组数据做出不错的猜测。就像,对于一个类似峰的函数,你可以说质心应该在数据的最大强度点附近,等等。对于一个数据集,可以在没有太多工作的情况下找到半高全宽,然后“ sigma" 可能在其中的一半左右。
为其他功能这样做需要一些启发式和常识,但它应该是可行的。
推荐阅读
- laravel - 请求get方法路由处理
- php - 当上传的文件名已存在于数据库中时,在处理 PHP 表单时显示警报
- android - 如何解决:应用程序安装被播放保护问题阻止
- vue.js - NPM 脚本“serve”退出,但没有表明服务器正在侦听请求:“npm”不是内部或外部命令
- git - 如何查看 Gerrit 中标签的创建者
- excel - PowerShell Excel 插入公式不起作用
- google-apps-script - 有没有办法通过 Appscript 或在工作表上按用户数量列出 Google Workspace 应用程序的使用情况
- javascript - MaterializeCSS onAutocomplete 不触发 javascript 回调函数
- javascript - String.prototype.indexOf() 的运行时复杂度是多少?
- c++ - 不能在 g++-11 中使用 -fsanitize=address