如何修复高斯拟合不符合预期?

huangapple go评论100阅读模式
英文:

How to fix gaussian fit not behaving like expected?

问题

我有一组数据,显示辐射的吸收与速度的函数关系。数据显示一个非常明显的低谷,或者如果我们绘制数据的倒数,即吸收度,我们会得到一个明显的峰值。我没有理由不相信这个峰值是一个高斯分布,想要进行拟合以获取这个峰值的方差。因此,我尝试使用scipy.optimize.curve_fit来实现这一目标,无论初始猜测如何,得到的拟合结果都相差很远。

我附上了代码和结果图:

  1. import matplotlib.pyplot as plt
  2. from scipy.optimize import curve_fit
  3. import numpy as np
  4. # 以下是数据的读取和处理部分,未翻译
  5. # ...
  6. def func(x, mu, sigma):
  7. return (1 / (np.sqrt(np.pi * 2) * sigma)) * np.exp(-0.5 * ((x - mu) / sigma) ** 2)
  8. data = np.array(cts)
  9. cts_norm = (data - data.min()) / (data.max() - data.min())
  10. cts_inv = 1 - cts_norm
  11. fit, error = curve_fit(func, vel, cts_inv, p0=[0.2, 0.2])
  12. print(fit)
  13. plt.plot(vel, cts_inv, 'bo')
  14. plt.plot(vel, func(vel, fit[0], fit[1]), 'r')

如何修复高斯拟合不符合预期?

请注意,以上是代码的翻译,没有包含问题的回答或其他内容。

英文:

I have a set of data showing radition not being absorbed as a function of velocity. The data shows a very clear dip or if we plot the inverse of the data the absorbtion, we get a clear peak instead. I have no reason not to belive this peak to be a gaussian and would like to make a fit to get the variance of this peak. So I've tried to use scipy.optimize.curve_fit, to achieve this. Both using scipy.stats.norm.pdf and a self written version of the function. No matter initial guesses. The resulting fit is way of.
I attached the code and a picture of the resulting graph.
What am I doing wrong? Are there any general tricks for these kind of tasks?

  1. import matplotlib.pyplot as plt
  2. from scipy.optimize import curve_fit
  3. import numpy as np
  4. cts = []
  5. vel = []
  6. file = open("Heisenberg/Mössbauer/Final.lst", "r")
  7. linesArr = file.readlines()
  8. for i in range(210, 260):
  9. lineList1 = linesArr[i].split()
  10. cts.append(int(lineList1[1]))
  11. chn = (int(lineList1[0]))
  12. tempVel = -0.04 * chn + 9.3
  13. vel.append(tempVel)
  14. def func (x, mu,sigma):
  15. return (1 / (np.sqrt(np.pi * 2) *sigma)) * np.exp(-0.5*((x-mu)/sigma)**2)
  16. data = np.array(cts)
  17. cts_norm = (data - data.min())/ (data.max() - data.min())
  18. cts_inv = 1 - cts_norm
  19. fit, error = curve_fit(func, vel, cts_inv, p0=[0.2, 0.2])
  20. print(fit)
  21. plt.plot(vel, cts_inv, 'bo')
  22. plt.plot(vel, func(vel, fit[0],fit[1]),"r")

如何修复高斯拟合不符合预期?

答案1

得分: 2

问题在于您试图拟合一个正态分布到不是概率分布的数据上!概率分布的积分等于1,但对于您的数据来说并非如此,它可以具有任何幅度。很难将您的数据归一化以满足这一要求。相反,您可以简单地添加一个新的参数来控制正态分布的“幅度”,如下所示:

  1. import matplotlib.pyplot as plt
  2. from scipy.optimize import curve_fit
  3. import numpy as np
  4. cts = [0, 0, 0, 0, -1, -2, -5, -10, -5, -2, -1, 0, 0, 0, 0]
  5. vel = np.linspace(-0.75, 1.25, 15)
  6. def func(x, mu, sigma, a):
  7. return a * np.exp(-0.5 * ((x - mu) / sigma) ** 2)
  8. data = np.array(cts)
  9. cts_norm = (data - data.min()) / (data.max() - data.min())
  10. cts_inv = 1 - cts_norm
  11. fit, error = curve_fit(func, vel, cts_inv, p0=[0.2, 0.2, 1])
  12. print(fit)
  13. plt.plot(vel, cts_inv, 'bo')
  14. plt.plot(vel, func(vel, fit[0], fit[1], fit[2]), "r")
  15. plt.show()

如何修复高斯拟合不符合预期?

(我使用了一些虚拟数据,因为我无法访问您的文件,但这并不重要)

英文:

The issue is that you are trying to fit a normal distribution with data that is not a probability distribution! Probability distributions have an integral equal to 1, but that is not the case for your data, which can have any amplitude. It would be hard to normalize your data to satisfy this. Instead, you can simply add a new parameter which controls the "amplitude" of the normal distribution, like below:

  1. import matplotlib.pyplot as plt
  2. from scipy.optimize import curve_fit
  3. import numpy as np
  4. cts = [0, 0, 0, 0, -1, -2, -5, -10, -5, -2, -1, 0, 0, 0, 0]
  5. vel = np.linspace(-0.75, 1.25, 15)
  6. def func(x, mu, sigma, a):
  7. return a * np.exp(-0.5 * ((x - mu) / sigma) ** 2) # << here
  8. data = np.array(cts)
  9. cts_norm = (data - data.min()) / (data.max() - data.min())
  10. cts_inv = 1 - cts_norm
  11. fit, error = curve_fit(func, vel, cts_inv, p0=[0.2, 0.2, 1]) # << here
  12. print(fit)
  13. plt.plot(vel, cts_inv, 'bo')
  14. plt.plot(vel, func(vel, fit[0], fit[1], fit[2]), "r") # << and here
  15. plt.show()

如何修复高斯拟合不符合预期?

(I used some dummy data as I don't have access to your file, but it doesn't really matter)

答案2

得分: 1

  1. 我会为你的模型添加一些灵活性具体如下我通过拍摄图像并使用 [此][1] 免费网络服务来检索了你的数据
  2. ```python
  3. import matplotlib.pyplot as plt
  4. import numpy as np
  5. from scipy.optimize import curve_fit
  6. from scipy.stats import norm
  7. data = np.loadtxt(r"C:\Users\Cristiano\Desktop\data.txt", delimiter=",")
  8. x = data[:, 0]
  9. y = data[:, 1]
  10. def f(x, a, b, mu, sigma):
  11. return a + b * np.exp(-(x - mu) ** 2 / (2 * sigma ** 2))
  12. popt, pcov = curve_fit(f, x, y)
  13. mean, std = norm.fit(data)
  14. plt.scatter(x, y)
  15. xx = np.linspace(-0.75, 1.25, 1000)
  16. plt.plot(xx, f(xx, *popt))
  17. plt.show()

如何修复高斯拟合不符合预期?

  1. <details>
  2. <summary>英文:</summary>
  3. I would add a little more flexibility to your model as follows. I retrieved your data by taking a screenshot of the image and using [this][1] free web service.
  4. ```python
  5. import matplotlib.pyplot as plt
  6. import numpy as np
  7. from scipy.optimize import curve_fit
  8. from scipy.stats import norm
  9. data = np.loadtxt(r&quot;C:\Users\Cristiano\Desktop\data.txt&quot;, delimiter=&quot;,&quot;)
  10. x = data[:, 0]
  11. y = data[:, 1]
  12. def f(x, a, b, mu, sigma):
  13. return a + b * np.exp(-(x - mu) ** 2 / (2 * sigma ** 2))
  14. popt, pcov = curve_fit(f, x, y)
  15. mean, std = norm.fit(data)
  16. plt.scatter(x, y)
  17. xx = np.linspace(-0.75, 1.25, 1000)
  18. plt.plot(xx, f(xx, *popt))
  19. plt.show()

如何修复高斯拟合不符合预期?

huangapple
  • 本文由 发表于 2023年1月9日 08:03:52
  • 转载请务必保留本文链接:https://go.coder-hub.com/75052177.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定