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

时间:2013-07-11 16:52:58

标签: java android gaussian estimation

我必须将高斯曲线拟合到一组噪声数据中,然后将其作为特定应用的FWHM。我用MATLAB演示了这个概念,MATLAB中的曲线拟合非常简单。

但是,我最终必须将代码翻译成Java / Android。我试图在Android中寻找可以帮助我将高斯曲线拟合到数据集的库,但我找不到任何东西。因此,我开始尝试学习所有涉及的数学,所以我可以手动完成。

我的问题:我如何评估单项高斯模型的三个参数(中心,宽度,高度)?我试着研究期望最大化算法,但这已经超出了我的想法。

一般来说,我认为它与错误最小化有关?我只是弄清楚将高斯曲线拟合到我的数据的逐步方法。

编辑:

我尝试的其中一件事已经涉及获取我的数据的自然对数,使用LSQR将抛物线拟合到结果,然后转换回来。但是,我得到的结果并不准确,可能是因为这种方法在某种程度上存在偏差。

如果您不知道如何进行参数估算,您是否还有其他建议将曲线拟合到我的数据中? (请记住,它必须是手动的,因为Android的统计库似乎相当有限)

2 个答案:

答案 0 :(得分:2)

我最近使用Apache Commons数学类做了类似的事情,特别是Levenberg-Marquardt Optimizer,CurveFitter和GaussianFunction类。

我用来准备数据的代码如下:

    // 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]);

然后实际执行拟合:

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;
        }
    }
}

你提到你的数据很吵;我包括了猜测,因为我必须适应具有高斯分布的峰值,这些峰值本身就形成了高斯形状。初始条件必须非常准确。如果我的猜测偏离了几个像素,我就可以在整个数据集上得到一个适合而不仅仅是峰值。我想如果没有适合的后备/更大的趋势,它就会失败。

GaussianFunction具有隐藏参数A,B,C和D,它们分别是y offset,幅度,质心位置和sigma。

我不知道关于Android的一件事,所以我不知道你是否能够使用这个软件包,但我在找一个相关的问题时发现了这个问题(我也在复制一个Matlab用Java编写的应用程序并不好玩,如果你还没想到它,可能会有所帮助!

答案 1 :(得分:2)

使用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());

结果将是标准,均值,西格玛,其中标准将是你的幅度。