简体   繁体   中英

How do I improve a Gaussian/Normal fit in Python 3.X by using a running median?

I have an array of 100x100 data points, where I'm trying to perform a Gaussian fit to each column of 100 values in the array. I then want the parameters of the Gaussian found by using the fit of the first column to be the initial parameters of the starting point for the next column to use. Let's say I start with the initial parameters of 1000, 0, and 1, and the fit finds values of 800, 3, and 1.5. I then want the fitter to use these three parameters as initial values for the next column.

My code is:

x = np.linspace(-50,50,100)
Gauss_Model = models.Gaussian1D(amplitude = 1000., mean = 0, stddev = 1.)
Fitting_Model = fitting.LevMarLSQFitter()

Fit_Data = []

for i in range(0, Data_Array.shape[0]):
    Fit_Data.append(Fitting_Model(Gauss_Model, x, Data_Array[:,i]))

Right now it uses the same initial values for every fit. Does anyone know how to perform such a running median/mean for a Gaussian fitting method? Would really appreciate any help or being pointed in the right direction, thanks!

I'm not familiar with the specific library you are using, but if you can get your fitted parameters out with something like fit_data[-1].amplitude or fit_data[-1].mean , then you could modify your loop to use something like:

for i in range(0, data_array.shape[0]):
    if fit_data:  # true if not an empty list
        Gauss_Model = models.Gaussian1D(amplitude=fit_data[-1].amplitude,
                                        mean=fit_data[-1].mean,
                                        stddev=fit_data[-1].stddev)
    fit_data.append(Fitting_Model(Gauss_Model, x, Data_Array[:,i]))

basically checking whether you have already fit a model, and if you have, use the most recent fitted amplitude, mean, and standard deviation as the starting point for your next Gauss_Model .

A thought: this might speed up your fitting, but it shouldn't result in a "better" fit to the 100 data points in each fit operation. Your resulting model is probably the best fit model to the data it was presented. If you want to estimate the error in the parameters of your model, you can use the fact that, for two normal distributions A ~ N(m_a, v_a) and B ~ N(m_b, v_b) , the distribution A + B will have mean m_a + m_b and variance is v_a + v_b . Thus, the distribution of your means will be N(sum(means)/n, sum(variances)/n) . Basically you can say that your true mean is centered at the mean of your means with standard deviation (sum(stddev)/sqrt(n)) .

I also cannot tell what library you are using, and the details of how to do this probably depend on the details of how that library stores the fitted values. I can say that for lmfit ( https://lmfit.github.io/lmfit-py/ ) we struggled with this sort of usage and arrived at a design that makes what you are trying to do pretty easy. With lmfit, you might compose this problem as:

import numpy as np
from lmfit import GaussianModel

x = np.linspace(-50,50,100)
# get Data_Array from somewhere....

# create a model for a Gaussian
Gauss_Model = GaussianModel()

# make a set of parameters, setting initial values
params = Gauss_Model.make_params(amplitude=1000, center=0, sigma=1.0)

Fit_Results = []

for i in range(Data_Array.shape[1]):
    result = Gauss_Model.fit(Data_Array[:, i], params, x=x)
    Fit_Results.append(result)
    # update `params` with the current best fit params for the next column
    params = result.params

Note that this works because lmfit is careful that Model.fit() will not alter the input parameters, and will put the resulting best-fit parameters for each fit in result.params .

And, if you decide you do want to have all columns use the original initial values, just comment out that last params = result.params .

Lmfit has a lot more bells and whistles, but I hope that helps you do what you need.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM