Chỉ cần thực hiện các chức năng mô hình được tham số hóa của tổng số Gaussians đơn. Chọn một giá trị tốt cho đoán ban đầu của bạn (đây là một bước thực sự quan trọng) và sau đó có scipy.optimize
tinh chỉnh các số đó một chút.
Đây là cách bạn có thể làm điều đó:
import numpy as np
import matplotlib.pyplot as plt
from scipy import optimize
data = np.genfromtxt('data.txt')
def gaussian(x, height, center, width, offset):
return height*np.exp(-(x - center)**2/(2*width**2)) + offset
def three_gaussians(x, h1, c1, w1, h2, c2, w2, h3, c3, w3, offset):
return (gaussian(x, h1, c1, w1, offset=0) +
gaussian(x, h2, c2, w2, offset=0) +
gaussian(x, h3, c3, w3, offset=0) + offset)
def two_gaussians(x, h1, c1, w1, h2, c2, w2, offset):
return three_gaussians(x, h1, c1, w1, h2, c2, w2, 0,0,1, offset)
errfunc3 = lambda p, x, y: (three_gaussians(x, *p) - y)**2
errfunc2 = lambda p, x, y: (two_gaussians(x, *p) - y)**2
guess3 = [0.49, 0.55, 0.01, 0.6, 0.61, 0.01, 1, 0.64, 0.01, 0] # I guess there are 3 peaks, 2 are clear, but between them there seems to be another one, based on the change in slope smoothness there
guess2 = [0.49, 0.55, 0.01, 1, 0.64, 0.01, 0] # I removed the peak I'm not too sure about
optim3, success = optimize.leastsq(errfunc3, guess3[:], args=(data[:,0], data[:,1]))
optim2, success = optimize.leastsq(errfunc2, guess2[:], args=(data[:,0], data[:,1]))
optim3
plt.plot(data[:,0], data[:,1], lw=5, c='g', label='measurement')
plt.plot(data[:,0], three_gaussians(data[:,0], *optim3),
lw=3, c='b', label='fit of 3 Gaussians')
plt.plot(data[:,0], two_gaussians(data[:,0], *optim2),
lw=1, c='r', ls='--', label='fit of 2 Gaussians')
plt.legend(loc='best')
plt.savefig('result.png')
Như bạn có thể thấy, hầu như không có sự khác biệt giữa hai phù hợp này (trực quan). Vì vậy, bạn không thể biết chắc chắn nếu có 3 Gaussians có mặt trong nguồn hoặc chỉ 2. Tuy nhiên, nếu bạn phải đoán, sau đó kiểm tra số dư nhỏ nhất:
err3 = np.sqrt(errfunc3(optim3, data[:,0], data[:,1])).sum()
err2 = np.sqrt(errfunc2(optim2, data[:,0], data[:,1])).sum()
print('Residual error when fitting 3 Gaussians: {}\n'
'Residual error when fitting 2 Gaussians: {}'.format(err3, err2))
# Residual error when fitting 3 Gaussians: 3.52000910965
# Residual error when fitting 2 Gaussians: 3.82054499044
Trong trường hợp này, 3 Gaussians cho kết quả tốt hơn, nhưng tôi cũng đã đoán ban đầu của tôi khá chính xác.
Câu hỏi của bạn không hoàn toàn rõ ràng: bạn có muốn phù hợp với Gaussian với dữ liệu của bạn (thay vì ồn ào) không? Bạn có muốn tìm vị trí của maxima không? Dữ liệu có tổng cộng 1-3 Gaussians và bạn muốn lấy phương sai trung bình và chuẩn của mỗi nhóm không? –
Xin chào! Cảm ơn bạn đã trả lời :) Tôi muốn phù hợp với một Gaussian cho mỗi đỉnh. – astromath
"Dữ liệu có tổng cộng 1-3 Gaussians và bạn muốn lấy phương sai trung bình và chuẩn của mỗi?" chính xác! – astromath