簡體   English   中英

python 上的高斯擬合直方圖似乎已關閉。 我可以改變什么來改善合身性?

[英]Gaussian fit to histogram on python seems off. What could I change to improve the fit?

我已經為繪制為條形圖的數據創建了高斯擬合。 但是,合身看起來不合適,我不知道要改變什么來改善合身。 我的代碼如下:

import matplotlib.pyplot as plt
import math
import numpy as np
from collections import Counter
import collections
from scipy.optimize import curve_fit
from scipy.stats import norm
from scipy import stats
import matplotlib.mlab as mlab

k_list = [-40, -32, -30, -28, -26, -24, -22, -20, -18, -16, -14, -12, -10, -8, -6, -4, -3, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34]
v_list = [1, 2, 11, 18, 65, 122, 291, 584, 1113, 2021, 3335, 5198, 7407, 10043, 12552, 14949, 1, 16599, 16770, 16728, 14772, 12475, 9932, 7186, 4987, 3286, 1950, 1080, 546, 285, 130, 54, 18, 11, 2, 2]

def func(x, A, beta, B, mu, sigma):
    return (A * np.exp(-x/beta) + B * np.exp(-100.0 * (x - mu)**2 / (2 * sigma**2))) #Normal distribution

popt, pcov = curve_fit(func, xdata=k_list, ydata=v_list, p0=[10000, 5, 10000, 10, 10])
print(popt)


x = np.linspace(-50, 50, 1000)

plt.bar(k_list, v_list, label='myPLOT', color = 'b', width = 0.75)
plt.plot(x, func(x, *popt), color='darkorange', linewidth=2.5, label=r'Fitted function')

plt.xlim((-30, 45))
plt.legend()
plt.show()

我得到的plot如下:

帶有擬合高斯曲線的條形圖

如何調整我的合身度?

您在這里有一個明顯的異常值,可能是由拼寫錯誤引起的: (k, v) == (-3, 1)在數據中的索引 16 處。

在此處輸入圖像描述

在這里,將數據表示為條形圖並不是最佳的。 如果您以與顯示擬合相同的格式顯示數據,則該問題將清晰可見。 以下任一方法會更好:

在此處輸入圖像描述

異常值迫使峰值下降。 如果我們手動刪除異常值,這是合適的:

在此處輸入圖像描述

您可以通過檢查其單個殘差與整個擬合的 RMSE 來自動刪除異常值:

popt, pcov = curve_fit(func, xdata=k_list, ydata=v_list, p0=[10000, 5, 10000, 10, 10])
resid = np.abs(func(k_list, *popt) - v_list)
rmse = np.std(resid)
keep = resid < 3 * rmse
if keep.sum() < keep.size:
     popt, pcov = curve_fit(func, xdata=k_list[keep], ydata=v_list[keep], p0=popt)

甚至是重復應用:

popt = [10000, 5, 10000, 10, 10]
while True:
    popt, pcov = curve_fit(func, xdata=k_list, ydata=v_list, p0=popt)
    resid = np.abs(func(k_list, *popt) - v_list)
    rmse = np.std(resid)
    keep = resid < 5 * rmse
    if keep.sum() == keep.size:
        break
    k_list = k_list[keep]
    v_list = v_list[keep]

經過幾次迭代后,3-sigma 異常值會從您的數據中剔除所有內容,因此我使用了 5-sigma。 請記住,這是一種非常快速且骯臟的數據去噪方法。 它實際上基本上是手動的,因為您必須重新檢查數據以確保您選擇的因素是正確的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM