python - 使用 python 将“多模式”对数正态分布拟合到数据中
问题描述
我使用实验室中的仪器测量了以下数据。由于仪器根据它们的直径将不同尺寸的颗粒收集在箱中,因此测量基本上是“分箱”的:
import numpy as np
import matplotlib.pylab as plt
from lmfit import models
y = np.array([196, 486, 968, 2262, 3321, 4203, 15072, 46789, 95201, 303494, 421484, 327507, 138931, 27973])
bins = np.array([0.0150, 0.0306, 0.0548, 0.0944, 0.1540, 0.2560, 0.3830, 0.6050, 0.9510, 1.6400, 2.4800, 3.6700, 5.3800, 9.9100, 15])
bin_width=np.diff(bins)
x_plot = np.add(bins[:-1],np.divide(bin_width,2))
x=x_plot
y=y
在这里绘制的是数据的外观。在 x 刻度的单位中,有一种模式约为 0.1,另一种模式约为 2。
在这个研究领域内,将“多峰”对数正态分布拟合到此类数据是很常见的:鉴于此,我使用 LMFIT 拟合了 2 左右的模式:
model = models.LognormalModel()
params = model.make_params(center=1.5, sigma=0.6, amplitude=2214337)
result = model.fit(y, params, x=x)
print(result.fit_report())
plt.plot(x, y, label='data')
plt.plot(x, result.best_fit, label='fit')
plt.xscale("log")
plt.yscale("log")
plt.legend()
plt.show()
正如预期的那样,这会很好地拟合 2 左右的第二种模式。我的问题是,我将如何去拟合 0.1 左右的第二种模式(基本上这两种模式的总和应该适合数据)?我意识到也可以说三种模式会更好,但我认为一旦我了解如何使用两种模式,添加第三种模式应该是微不足道的。
解决方案
lmfit.Models
可以加在一起,如:
model = (models.LognormalModel(prefix='p1_') +
models.LognormalModel(prefix='p2_') +
models.LognormalModel(prefix='p3_') )
params = model.make_params(p1_center=0.3, p1_sigma=0.2, p1_amplitude=1e4,
p2_center=1.0, p2_sigma=0.4, p2_amplitude=1e6,
p3_center=1.5, p3_sigma=0.6, p3_amplitude=2e7)
在复合模型中,模型的每个组件都有自己的“前缀”(任何字符串),该前缀位于参数名称之前。拟合后,您可以获得模型组件的字典:
components = result.eval_components()
# {'p1_': Array, 'p2_': Array, 'p3_': Array}
for compname, comp in components.keys():
plt.plot(x, comp, label=compname)
为了拟合您将在半对数或对数对数图中表示的数据,您可以考虑将模型拟合到log(y)
. 否则,在 非常低的值下,拟合不会对失配非常敏感y
。
请注意,lmfit
模型和参数支持边界。您可能想要或发现您需要设置边界,例如
params['p1_amplitude'].min = 0
params['p1_sigma'].min = 0
params['p1_center'].max = 0.5
params['p3_center'].min = 1.0
推荐阅读
- java - 在 Java 中更新字符串
- python - 将数据从 Excel 工作簿复制到另一个工作簿,需要选择特定的行和列
- python - 有没有一种方法可以在键盘记录文件('user_logs.txt')中每次输入内容时都无法在新行上打印?
- python - 我不想要 discord.py-rewrite
- ietf-netmod-yang - Yang action vs rpc 和 anydata vs anyxml
- google-apps-script - TypeError:无法调用 null 的方法“getActiveSheet”。在 myFunction(代码:6)
- javascript - TypeScript - 如何防止在构造函数中使用变量覆盖类方法
- java - 不连接数据库?
- django - 用作 ForeignKey 的 ImageField 中的图像 url
- javascript - 如何异步调用 3 个请求?