python - 如何使用 Astropy 拟合高斯分布

标签 python jupyter-notebook gaussian astropy

我正在尝试使用 astropy.modeling 包将高斯拟合到一组数据点,但我得到的只是一条平线。见下文:

/image/H37VC.png

/image/DOKSd.png

这是我的代码:

%pylab inline
from astropy.modeling import models,fitting
from astropy import modeling

#Fitting a gaussian for the absorption lines
wavelength= linspace(galaxy1_wavelength_extracted_1.min(),galaxy1_wavelength_extracted_1.max(),200)
g_init = models.Gaussian1D(amplitude=1., mean=5000, stddev=1.)
fit_g = fitting.LevMarLSQFitter()
g = fit_g(g_init, galaxy1_wavelength_extracted_1, galaxy1_flux_extracted_1)

#Plotting 
plot(galaxy1_wavelength_extracted_1,galaxy1_flux_extracted_1,".k")
plot(wavelength, g(wavelength))
xlabel("Wavelength ($\\AA$)")
ylabel("Flux (counts)")

我做错了什么或遗漏了什么?

最佳答案

我制作了一些类似于您的假数据,并尝试在其上运行您的代码并获得了类似的结果。我认为问题在于,如果您不将模型的初始参数调整到至少与原始模型相似,否则无论执行多少轮拟合,拟合器都无法收敛。

如果我要拟合高斯分布,我喜欢给初始模型一些初始参数,这些初始参数基于计算上的“目测”,就像这样(在这里我将您的真实数据的通量和波长命名为 orig_fluxorig_wavelength 分别):

>>> an_amplitude = orig_flux.min()
>>> an_mean = orig_wavelength[orig_flux.argmin()]
>>> an_stddev = np.sqrt(np.sum((orig_wavelength - an_mean)**2) / (len(orig_wavelength) - 1))
>>> print(f'mean: {an_mean}, stddev: {an_stddev}, amplitude: {an_amplitude}')
mean: 5737.979797979798, stddev: 42.768052162734605, amplitude: 84.73925092448636

对于标准偏差,我使用了 unbiased standard deviation estimate .

在我的假数据上绘制此图表明,如果我也手动观察数据,这些是我可能会选择的合理值:

>>> plt.plot(orig_wavelength, orig_flux, '.k', zorder=1)
>>> plt.scatter(an_mean, an_amplitude, color='red', s=100, zorder=2)
>>> plt.vlines([an_mean - an_stddev, an_mean + an_stddev], orig_flux.min(), orig_flux.max(),
...            linestyles='dashed', colors='gg', zorder=2)

enter image description here

我过去想添加到 astropy.modeling 的一个功能是可选方法,可以附加到某些模型以根据某些数据对其参数进行合理估计。所以对于 Gaussians 这样的方法会返回很像我刚刚在上面计算的结果。不过,我不知道这是否曾经实现过。

同样值得注意的是,您的高斯分布将被反转(具有负振幅)并且它在通量轴上位移了大约 120 个点,因此我添加了一个 Const1D。到我的模型来解释这一点,并从振幅中减去位移:

>>> an_disp = orig_flux.max()
>>> g_init = (
...     models.Const1D(an_disp) +
...     models.Gaussian1D(amplitude=(an_amplitude - an_disp), mean=an_mean, stddev=an_stddev)
... )
>>> fit_g = fitting.LevMarLSQFitter()
>>> g = fit_g(g_init, orig_wavelength, orig_flux)

这导致以下拟合看起来已经好多了:

>>> plt.plot(orig_wavelength, orig_flux, '.k')
>>> plt.plot(orig_wavelength, g(orig_wavelength), 'r-')

enter image description here

我不是建模或统计方面的专家,所以知识渊博的人可能会对此有所改进。我添加了一个笔记本,其中包含我对问题的完整分析,包括我如何生成示例数据 here .

关于python - 如何使用 Astropy 拟合高斯分布,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61295585/

相关文章:

python - 评估高斯拟合

python - 如何在 scipy 中集成一个 numpy 数组?

python - 避免自动填充 pd.MultiIndex 中的缺失值

javascript - 为什么 python 不能从 python 函数中调用 Javascript()?

jupyter-notebook - 将 nbconvert 升级到 6.x+ 时如何解决 TemplateNotFound 错误?

python-3.x - 笔记本验证失败

PHP应用强模糊的最快方法

python - 相同数据和簇数的不同轮廓分数

python - 在 Python 中转换为数据框

python - Pandas 滚动窗口函数偏移数据