1

我必须将高斯曲线拟合到一组嘈杂的数据中,然后将它的 FWHM 用于某个应用程序。我使用 MATLAB 来演示这个概念,在 MATLAB 中进行曲线拟合非常容易。

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

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

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

编辑:

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

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

4

2 回答 2

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 偏移、幅度、质心位置和 sigma。

我对Android一无所知,所以我不知道你是否可以使用这个包,但我在寻找相关问题时发现了这个问题(我也在用Java复制一个Matlab应用程序,不好玩),如果你还没有弄清楚,这可能会有所帮助!

于 2013-08-15T22:05:25.000 回答
2

使用 3.3 版本的 org.apache.commons.math3 使用 GaussianCurveFitter 更加容易:

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

结果将是范数、平均值、西格玛,其中范数将是您的幅度。

于 2014-06-10T21:10:57.867 回答