简体   繁体   English

高斯曲线拟合 - 参数估计 - Android / Java

[英]Gaussian Curve Fitting - Parameter Estimation - Android/Java

I have to fit a Gaussian curve to a noisy set of data and then take it's FWHM for a certain application. 我必须将高斯曲线拟合到一组噪声数据中,然后将其作为特定应用的FWHM。 I used MATLAB to demo the concept, and curve fitting in MATLAB is extremely easy. 我用MATLAB演示了这个概念,MATLAB中的曲线拟合非常简单。

However, I eventually have to translate the code into Java/Android. 但是,我最终必须将代码转换为Java / Android。 I tried looking for libraries in Android that would help me fit a Gaussian curve to data set, but I couldn't find anything. 我试图在Android中寻找可以帮助我将高斯曲线拟合到数据集的库,但我找不到任何东西。 Consequently, I started trying to learn all the math involved so I could do it manually. 因此,我开始尝试学习所有涉及的数学,所以我可以手动完成。

My question: How do I go about estimating the three parameters (center, width, height) for a single-term gaussian model? 我的问题:我如何评估单项高斯模型的三个参数(中心,宽度,高度)? I tried looking into the Expectation-Maximization algorithm but that went way over my head. 我试着研究期望最大化算法,但这已经超出了我的想象。

In general, I assume it would have something to do with error minimization? 一般来说,我认为它与错误最小化有关? I'm just having trouble figuring out the step-by-step method of fitting a gaussian curve to my data. 我只是在弄清楚将高斯曲线拟合到我的数据中的逐步方法。

EDIT: 编辑:

One of the things I tried already involved taking the natural log of my data, fitting a parabola to the result using LSQR, and then transforming back. 我尝试过的其中一件事涉及获取我的数据的自然对数,使用LSQR将抛物线拟合到结果,然后转换回来。 However, the results I'm getting aren't accurate, probably because this method is biased in some way or another. 但是,我得到的结果并不准确,可能是因为这种方法在某种程度上存在偏差。

If you don't know how to do parameter estimation, do you have any other suggestions of fitting a curve to my data? 如果您不知道如何进行参数估算,您还有其他建议将曲线拟合到我的数据中吗? (Remember, it has to be manual since Android seems to be fairly limited on it's statistics libraries) (请记住,它必须是手动的,因为Android的统计库似乎相当有限)

I recently did a similar thing using the Apache Commons math class, specifically the Levenberg-Marquardt Optimizer, CurveFitter, and GaussianFunction classes. 我最近使用Apache Commons数学类做了类似的事情,特别是Levenberg-Marquardt Optimizer,CurveFitter和GaussianFunction类。

The code I used to get the data ready was something like: 我用来准备数据的代码如下:

    // Initialize analyzers
    _optimizer = new LevenbergMarquardtOptimizer();
    _fitter = new CurveFitter(_optimizer);

    // Initialize the analysis results
    _gaussians = new ArrayList<GaussianFunction>();

    // Load the data into the gaussian fitter
    for (int i = 0; i != data.length; i++)
        _fitter.addObservedPoint(i, data[i]);

and then to actually perform the fit: 然后实际执行拟合:

public void analyze() {
    // Calculate Mean
    double sum_yx = 0.0;
    double sum_y = 0.0;
    for (int i = 0; i != _data.length; i++) {
        sum_yx += _data[i] * (i + 1);
        sum_y += _data[i];
    }

    double mean = sum_yx / sum_y;

    // Peform the gaussian fit

    // If no guesses given, fit to the mean of the data
    if (_guesses.size() == 0) {
        double[] guess = new double[] { 0, 1, mean, 1 };
        double ret[];
        try {
            ret = _fitter.fit(new ParametricGaussianFunction(), guess);
            _gaussians.add(new GaussianFunction(ret[0], ret[1], ret[2],
                    ret[3]));
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    // If guesses are given, fit to each one
    else {
        try {
            for (double[] guess : _guesses) {
                double ret[] = _fitter.fit(
                        new ParametricGaussianFunction(), guess);
                _gaussians.add(new GaussianFunction(ret[0], ret[1], ret[2],
                        ret[3]));
            }
        } catch (Exception e) {
            e.printStackTrace();
            // _gaussian = null;
        }
    }
}

You mentioned your data is noisy; 你提到你的数据很吵; I included the guesses because I had to fit to peaks with Gaussianish distributions that formed a Gaussian shape themselves. 我包括了猜测,因为我必须适应具有高斯分布的峰值,这些峰值本身就形成了高斯形状。 The initial condition has to be very accurate. 初始条件必须非常准确。 If my guesses were off by a few pixels, I got a fit over the entire data set instead of just the peak. 如果我的猜测偏离了几个像素,我就可以在整个数据集上得到一个适合而不仅仅是峰值。 I imagine if there's no fallback / larger trend to fit to, it would just fail. 我想如果没有适合的后备/更大的趋势,它就会失败。

GaussianFunction has the cryptic parameters A, B, C, and D which are, respectively, y offset, amplitude, centroid position, and sigma. GaussianFunction具有隐藏参数A,B,C和D,它们分别是y offset,幅度,质心位置和sigma。

I don't know a single thing about Android, so I don't know if you'll be able to use this package, but I found this question while looking for a related one (I'm also replicating a Matlab application in Java, not fun) and figured if you haven't figured it out yet, this might help! 我不知道关于Android的一件事,所以我不知道你是否能够使用这个软件包,但我在找一个相关的问题时发现了这个问题(我也在用Java复制一个Matlab应用程序) ,并不好玩)并想到如果你还没想到它,这可能会有所帮助!

With 3.3 version of org.apache.commons.math3 is even easier using GaussianCurveFitter: 使用GaussianCurveFitter可以更轻松地使用3.3版本的org.apache.commons.math3:

        GaussianCurveFitter fitter = GaussianCurveFitter.create();

        WeightedObservedPoints obs = new WeightedObservedPoints();

        for (int index = 0; index < data.length; index++) {
            obs.add(data[i].x, data[i].y);
        }

        double[] bestFit = fitter.fit(obs.toList());

The results will be norm, mean, sigma, where norm will be your amplitude. 结果将是标准,均值,sigma,其中范数将是您的幅度。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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