Подгонка лучшего гауссова к точкам данных?

Я пытаюсь подогнать гауссиан к набору точек данных, которые, кажется, следуют гауссовскому распределению. Я уже проверил много возможных способов сделать это, но я действительно не понимаю большинство из них. Тем не менее, я нашел одно решение, которое, кажется, работает, но фактическая подгонка, которую я получаю, не намного больше похожа на гауссову, чем мои точки данных.

Вот мой код:

import numpy as np
import matplotlib.pyplot as plt
from scipy import asarray as ar, exp, sqrt
from scipy.optimize import curve_fit


angles = [-8, -6, -4, -2, 0, 2, 4, 6, 8]
data = [99, 610, 1271, 1804, 1823, 1346, 635, 125, 24]
angles = ar(angles)
data = ar(data)

n = len(x)
mean = sum(data*angles)/n
sigma = sqrt(sum(data*(angles-mean)**2)/n)

def gaus(x,a,mu,sigma):
    return a*exp(-(x-mu)**2/(2*sigma**2))

popt,pcov = curve_fit(gaus,angles,data,p0=[0.18,mean,sigma])


fig = plt.figure()
plt.plot(angles, data, "ob", label = "Measured")
plt.plot(angles,gaus(angles,*popt),'r',label='Fit')
plt.xlim(-10, 10)
plt.ylim(0, 2000)
plt.xticks(angles)
plt.title("$^{137}$Cs Zero Point")
plt.xlabel("Angle [$^\circ$]")
plt.ylabel("662 keV-Photon Count")
plt.grid()
plt.legend()
plt.show()

Это вывод, который он генерирует:

подгонка по Гауссу

Как видите, подгонка не описывает красивую и симметричную «настоящую» гауссову функцию. Есть ли способ получить «лучший» гауссиан или это настолько хорошо, насколько это возможно?

Большое спасибо!


person Philipp    schedule 03.02.2017    source источник
comment
n = len(x) был, может быть, n = len(data) ?   -  person Luis    schedule 03.02.2017


Ответы (2)


Я думаю, что здесь две разные вещи:

кажется, следует распределению Гаусса

→ Если вы считаете, что данные распределены нормально, вы занимаетесь статистикой и распределением вероятностей и можете провести проверить, чтобы увидеть, согласуются ли они с определенным распределением (нормальным или другим).


И работайте со своим графиком:

получить "лучший" гауссовский график

В своем коде вы можете опустить первую оценку в curve_fit и построить построенную кривую в зависимости от непрерывной независимой переменной:

import numpy as np
import matplotlib.pyplot as plt
from scipy import asarray as ar, exp, sqrt
from scipy.optimize import curve_fit


angles = [-8, -6, -4, -2, 0, 2, 4, 6, 8]
data = [99, 610, 1271, 1804, 1823, 1346, 635, 125, 24]
angles = ar(angles)
data = ar(data)

n = len(data)  ## <---
mean = sum(data*angles)/n
sigma = sqrt(sum(data*(angles-mean)**2)/n)

def gaus(x,a,mu,sigma):
    return a*exp(-(x-mu)**2/(2*sigma**2))

popt,pcov = curve_fit(gaus,angles,data)#,p0=[0.18,mean,sigma])  ## <--- leave out the first estimation of the parameters
xx = np.linspace( -10, 10, 100 )  ## <--- calculate against a continuous variable

fig = plt.figure()
plt.plot(angles, data, "ob", label = "Measured")
plt.plot(xx,gaus(xx,*popt),'r',label='Fit')  ## <--- plot against the contious variable
plt.xlim(-10, 10)
plt.ylim(0, 2000)
plt.xticks(angles)
plt.title("$^{137}$Cs Zero Point")
plt.xlabel("Angle [$^\circ$]")
plt.ylabel("662 keV-Photon Count")
plt.grid()
plt.legend()
plt.savefig('normal.png')
plt.show()

введите здесь описание изображения


В этом примере:

print( popt )

[  1.93154077e+03  -9.21486804e-01   3.26251063e+00]

Обратите внимание, что первая оценка параметра на несколько порядков отличается от результата: 0,18 против 1931,15.

person Luis    schedule 03.02.2017

Лучший способ - просто использовать среднее значение и дисперсию точек. Я имею в виду, что если у вас есть доступ к базовым данным, которые создали эту гистограмму, вы должны вычислить ее среднее значение и дисперсию, используя функции mean и var.

Гистограмма — это просто визуальное приближение к базовым данным, и, по сути, вы оцениваете среднее значение и дисперсию окольным путем, подбирая гистограмму вместо данных.

В любом случае, если вы хотите продолжить ход мыслей выше, вам нужно добавить больше точек к углам. Лучший способ сделать это - сделать что-то вроде

angles2 = np.arange(-8,8,.1);
plt.plot(angles2,gaus(angles2,*popt),'r',label='Fit')

Возможно, ваша подгонка выглядит плохо, потому что у вас очень мало точек данных. Используя этот подход, вы увидите, как должно выглядеть непрерывное распределение.

person bremen_matt    schedule 03.02.2017
comment
The best way is to simply use the mean and variance of the points - Я согласен, но вы можете обосновать это утверждение :) - person cel; 03.02.2017
comment
И как бы я получил гауссовскую подгонку от этого? - person Philipp; 03.02.2017
comment
@Philipp, вы в основном оцениваете среднее значение и стандартное отклонение гауссова от данных. Это параметры вашего распределения Гаусса. Если вы подставите их в функцию плотности вероятности (то есть гауссову), вы получите форму, которую искали. - person cel; 03.02.2017
comment
@cel, понятно. Насколько аккуратно выглядел бы код в моем примере с использованием mean и var? - person Philipp; 03.02.2017