由于数据值看起来太小,无法使用 lmfit 进行高斯拟合

Trouble fitting Gaussian fit using lmfit due to data values appearing to be too small

我正在尝试使用 lmfit 模块对以下数据进行高斯拟合:

x = np.array([-1.36534351e-09, -1.29984067e-09, -1.23433782e-09, -1.16883498e-09,
-1.10333214e-09, -1.03782929e-09, -9.72326447e-10, -9.06823602e-10,
-8.41320758e-10, -7.75817913e-10, -7.10315069e-10, -6.44812224e-10,
-5.79309380e-10, -5.13806535e-10, -4.48303691e-10, -3.82800846e-10,
-3.17298002e-10, -2.51795157e-10, -1.86292313e-10, -1.20789468e-10,
-5.52866238e-11,  1.02162207e-11,  7.57190652e-11,  1.41221910e-10,
 2.06724754e-10,  2.72227599e-10,  3.37730443e-10,  4.03233288e-10,
 4.68736132e-10,  5.34238977e-10,  5.99741821e-10,  6.65244666e-10,
 7.30747510e-10,  7.96250355e-10,  8.61753199e-10,  9.27256043e-10,
 9.92758888e-10,  1.05826173e-09,  1.12376458e-09,  1.18926742e-09,
 1.25477027e-09,  1.32027311e-09,  1.38577595e-09,  1.45127880e-09,
 1.51678164e-09,  1.58228449e-09,  1.64778733e-09,  1.71329018e-09,
 1.77879302e-09,  1.84429587e-09])

y = np.array([  2,   0,   0,   0,   1,   0,   0,   1,   0,   1,   2,   4,   7,   8,  17,  13,  45,  
77, 182, 346, 494, 512, 443, 327, 192, 115,  62,  28,  20,  16,  13,   5,   6,   2,   1,   0,     
0,   2,   4,   1,   2,   2,   1,   2,   2,   1,   2,   2,   0,   1])

当我拟合数据并绘制它时,我得到以下结果:

有趣的是,如果我将 x 数据数组乘以 100,拟合效果似乎很好:

我怀疑这可能是由于最初的猜测不准确,但我仍然不太清楚为什么会这样,以及我该如何解决这个问题。我在下面包含了完整的代码:

import matplotlib.pyplot as plt
from lmfit.models import GaussianModel
import numpy as np


x = np.array([-1.36534351e-09, -1.29984067e-09, -1.23433782e-09, -1.16883498e-09,
 -1.10333214e-09, -1.03782929e-09, -9.72326447e-10, -9.06823602e-10,
 -8.41320758e-10, -7.75817913e-10, -7.10315069e-10, -6.44812224e-10,
 -5.79309380e-10, -5.13806535e-10, -4.48303691e-10, -3.82800846e-10,
 -3.17298002e-10, -2.51795157e-10, -1.86292313e-10, -1.20789468e-10,
 -5.52866238e-11,  1.02162207e-11,  7.57190652e-11,  1.41221910e-10,
  2.06724754e-10,  2.72227599e-10,  3.37730443e-10,  4.03233288e-10,
  4.68736132e-10,  5.34238977e-10,  5.99741821e-10,  6.65244666e-10,
  7.30747510e-10,  7.96250355e-10,  8.61753199e-10,  9.27256043e-10,
  9.92758888e-10,  1.05826173e-09,  1.12376458e-09,  1.18926742e-09,
  1.25477027e-09,  1.32027311e-09,  1.38577595e-09,  1.45127880e-09,
  1.51678164e-09,  1.58228449e-09,  1.64778733e-09,  1.71329018e-09,
  1.77879302e-09,  1.84429587e-09])
y = np.array([  2,   0,   0,   0,   1,   0,   0,   1,   0,   1,   2,   4,   7,   8,  17,  13,  45,  
77, 182, 346, 494, 512, 443, 327, 192, 115,  62,  28,  20,  16,  13,   5,   6,   2,   1,   0, 0,   2,   
4,   1,   2,   2,   1,   2,   2,   1,   2,   2,   0,   1])

mod = GaussianModel()
pars = mod.guess(y, x=x)                       
final_fit = mod.fit(y, pars, x=x)

plt.plot(x, final_fit.init_fit, label='Initial fit')
plt.plot(x, final_fit.best_fit, label='Gaussian fit')
plt.scatter(x, y, label='data points')
plt.show()

更新: 我已经在另一台计算机上测试了完全相同的程序,结果证明它在那里工作得很好。现在,我不太确定。

正如 Jan Christoph Terasa 评论的那样,您的 x 值的精度几乎肯定是问题所在。进行拟合时,底层算法需要对参数值进行较小的相对更改,以查看这对拟合有何影响。更改通常在 1.e-7 级别。这意味着当使用 1e.-9 级别的值时,更改将接近机器精度并且可能对结果没有影响(并且,是的,这可能取决于机器细节)。

解决方案是更改 x 和/或 y 数据的比例,使其在 1.e-6 到 1.e6 的范围内.幸运的是,对于您的情况,您似乎可以通过乘以 1e9 并以 "nano-x".

为单位来更改 x