2017-10-21 1 views
1

나는 성공적으로 scipy에서 곡선 맞춤을 사용하여 가우스 피팅을 구현하는 믿습니다. 하지만 내가 겪고있는 문제는 최적화가 매개 변수가 중심을 변경하기 때문에 적합성이 그리 좋지 않다는 것입니다.*** 사용하여 가우스 피팅 향상 *** scipy 및 python 3.x

data =np.loadtxt('mock.txt') 
    my_x=data[:,0] 
    my_y=data[:,1] 

    def gauss(x,mu,sigma,A): 
     return A*np.exp(-(x-mu)**2/2/sigma**2) 
    def trimodal_gauss(x,mu1,sigma1,A1,mu2,sigma2,A2,mu3,sigma3,A3): 
     return gauss(x,mu1,sigma1,A1)+gauss(x,mu2,sigma2,A2)+gauss(x,mu3,sigma3,A3) 



    """"" 
    Gaussian fitting parameters recognized in each file 
    """"" 
    first_centroid=(10180.4*2+9)/9 
    second_centroid=(10180.4*2+(58.6934*1)+7)/9 
    third_centroid=(10180.4*2+(58.6934*2)+5)/9 
    centroid=[] 
    centroid+=(first_centroid,second_centroid,third_centroid) 

    apparent_resolving_power=1200 
    sigma=[] 
    for i in range(len(centroid)): 
     sigma.append(centroid[i]/((apparent_resolving_power)*2.355)) 

    height=[1,1,1] 

    p=[]  

    p = np.array([list(t) for t in zip(centroid, sigma, height)]).flatten() 


    popt, pcov = curve_fit(trimodal_gauss,my_x,my_y,p0=p) 

출력 : enter image description here

내가 거기 피크의 많은 현재 위치하지만 난 정말 세 개의 가우시안에 맞게 할 필요가 있지만, 올바른 중심에서 (내 초기 추측에 주어진)을 이해합니다. 다른 말로 표현하자면, 내가주는 중심이 변하지 않기를 바란다. 누구도 그러한 도전을 경험 했습니까? 그 일이 가능하도록 내가 도와 줄 수 있겠 니?

+0

, 당신이 더 정확한 숫자를 맞는 것 같다 (적어도 5, 어쩌면 6)의 3 가지 결과 만 가져옵니다. 피팅하지 않은 봉우리가 관심있는 세 가지 봉우리의 결과에 영향을 미치기 때문에 현재의 접근 방식은 좋지 않습니다. 추가 재료가 3 개의 봉우리의 일부라고 생각할 것입니다. 귀하의 의견에 – NichtJens

답변

0

, 당신은 쉽게 가우스 함수의 무게 중심에 경계를 넣어, 또는 그 문제를 해결할 수 있습니다. Lmfit을 사용하면 멀티 피크 모델을 쉽게 만들 수 있습니다.

당신은 당신의 데이터에 대한 완벽한 예 또는 링크를 제공하지 않았지만, 데이터에 lmfit에 적합은 다음과 같습니다 일반적으로

import numpy as np 
from lmfit import GaussianModel 
data =np.loadtxt('mock.txt') 
my_x=data[:,0] 
my_y=data[:,1] 

model = (GaussianModel(prefix='p1_') + 
      GaussianModel(prefix='p2_') + 
      GaussianModel(prefix='p3_')) 

params = model.make_params(p1_amplitude=100, p1_sigma=2, p1_center=2262, 
          p2_amplitude=100, p2_sigma=2, p2_center=2269, 
          p3_amplitude=100, p3_sigma=2, p3_center=2276, 
         ) 

# set boundaries on the Gaussian Centers: 
params['p1_center'].min = 2260 
params['p1_center'].max = 2264 

params['p2_center'].min = 2267 
params['p2_center'].max = 2273 

params['p3_center'].min = 2274 
params['p3_center'].max = 2279 

# or you could just fix one of the centroids like this: 
params['p3_center'].vary = False 

# if needed, you could force all the sigmas to be the same value 
# or related by simple mathematical expressions 
params['p2_sigma'].expr = 'p1_sigma' 
params['p3_sigma'].expr = '2*p1_sigma' 

# fit this model to data: 
result = model.fit(my_y, params, x=my_x) 

# print results 
print(result.fit_report()) 

# evaluate individual gaussian components: 
peaks = model.eval_components(params=result.params, x=my_x) 

# plot results: 
plt.plot(my_x, my_y, label='data') 
plt.plot(my_x, result.best_fit, label='best fit') 
plt.plot(my_x, peaks['p1_']) 
plt.plot(my_x, peaks['p2_']) 
plt.plot(my_x, peaks['p3_']) 
plt.show() 
+0

'scipy.curve_fit'는 현재 버전에서 경계를 잘 알고 있습니다. https://stackoverflow.com/questions/16760788/python-curve-fit-library-that-allows-me-to-assign-bounds-to-parameters를 참조하십시오. – NichtJens

0

센터에 대해 고정 값으로 세 개의 별도 함수를 정의해야합니다. 그런 다음 남은 매개 변수에 대해서만이 함수의 합계 함수를 맞 춥니 다.

은 단순히 trimodal_gauss() mu의 만 A들과 sigma의을 안 넣어. mu은 상수 여야합니다.

이 일의 사소한 (하지만 매우 일반적되지 않음) 방법은이 일에서

def trimodal_gauss(x, sigma1, A1, sigma2, A2, sigma3, A3): 
    mu1 = 1234 # put your mu's here 
    mu2 = 2345 
    mu3 = 3456 
    g1 = gauss(x, mu1, sigma1, A1) 
    g2 = gauss(x, mu2, sigma2, A2) 
    g3 = gauss(x, mu3, sigma3, A3) 
    return g1 + g2 + g3 

이 세 가지 걸리는 trimodal_gauss 기능을위한 "발전기"에 의해 아이디어를 일반화 할 수 mu (또는 n을?) 다른 매개 변수의 기능을 생성합니다. 그래서 같이 : 당신이 lmfit 모듈 (https://github.com/lmfit/lmfit-py)를 사용하는 경우

def make_trimodal_gauss(mu1, mu2, mu3): 
    def result_function(x, sigma1, A1, sigma2, A2, sigma3, A3): 
     g1 = gauss(x, mu1, sigma1, A1) 
     g2 = gauss(x, mu2, sigma2, A2) 
     g3 = gauss(x, mu3, sigma3, A3) 
     return g1 + g2 + g3 
    return result_function 


mu1 = 1234 # put your mu's here 
mu2 = 2345 
mu3 = 3456 

trimodal_gauss = make_trimodal_gauss(mu1, mu2, mu3) 

#usage like this: trimodal_gauss(x, sigma1, A1, sigma2, A2, sigma3, A3) 
+0

주셔서 감사합니다. mu가 함수의 일부가 아니라면 가우시안이 관심 중심에 적합하도록하려면 어떻게해야할까요? – user7852656

+0

나는 내 대답에 그것을 한 가지 방법을 추가했습니다. – NichtJens