将数据估计/拟合到 Android 中的 exGaussian 分布
Estimate / fit data to exGaussian distribution in Android
如何使用 JAVA/Android estimate/fit 指数修正高斯分布 (exGaussian) 的参数?
我需要如下伪代码:
// some observed data points
double dataPoints[] = {200,300,400,278,366,466,325,335,322,332};
// ex-gaussian distribution
ExponentiallyModifiedGaussianDistribution exGaussian = new ExponentiallyModifiedGaussianDistribution();
// MLE
MaximumLikelihoodEstimation MLE = new MaximumLikelihoodEstimation(dataPoints, exGaussian);
MLE.setGuess(3.0, 1.0, 1.0);
MLE.compute();
// get estimated / fitted parameters
double[] parameterEstimates = MLE.getEstimates();
有一些示例演示了 Gamma Distribution 的参数估计。但是这个lib好像没有开源。
而且我在 JAVA 中找到了一个 ex-gaussian distribution implementation。但是缺少参数估计。
我认为有很多方法可以估计参数,例如使用 最大似然估计 (MLE) 等
更新 1:
我会避免使用 less than 40 dataPoints。
更新二:
估计分布参数的一种简单替代方法是矩估计法 (described on wiki)
也许您可以在 stats.stackexchange.com 上得到更好的答案。
但我认为您可以创建一个进行矩匹配的优化算法。基本上你需要最小化样本数据和理论分布之间的第一矩(均值)、第二矩(方差)、第三矩(偏度)等的差异。
您可以将 objective 函数视为矩的和或乘积。您还可以对时刻使用不同的权重(均值获得更高的权重)。
求objective函数的导数可以尝试使用梯度下降法(使用Mathematica或Sage math),甚至可以使用有限差分法对导数进行数值计算。这种方法大量用于估计回归、逻辑回归和人工神经网络的参数。
您还可以使用元启发式算法(遗传、禁忌搜索等)。
估计分布参数的一种简单替代方法是矩量法 (described on wiki)。
实施:
// some observed data points
double dataPoints[] = {0.464,0.443,0.424,0.386,0.367,0.382,0.455,0.410,0.411,0.424,0.338,0.355,0.342,0.324,
0.354,0.322,0.364,0.375,1.085,0.575,0.597,0.464,0.414,0.408,1.156,0.819,1.156,1.024,1.152,1.103,
0.431,0.378,0.358,0.382,0.354,0.435,0.386,0.361,0.397,0.362,0.334,0.357,0.344,0.362,0.317,0.331,
0.199,0.351,0.284,0.343,0.354,0.336,0.280,0.312,0.778,0.723,0.755,0.774,0.759,0.762,0.490,0.400,
0.364,0.439,0.441,0.673};
DescriptiveStatistics maths = new DescriptiveStatistics(dataPoints);
double sampleMean = maths.getMean();
double sampleStdDev = maths.getStandardDeviation();
double sampleSkev = (Math.abs(sampleMean - maths.getPercentile(50)) / sampleStdDev);
// parameter estimation using method of moments ex-gaussian distribution
double mean = sampleMean - sampleStdDev * Math.pow(sampleSkev/2., 1./3) ;
double stdDev = Math.sqrt(sampleStdDev*(1 - Math.pow(sampleSkev/2., 2./3)));
double tau = sampleStdDev * (Math.pow(sampleSkev/2., 1./3));
double lambda = 1 / tau;
ExponentiallyModifiedGaussianDistribution exGaussian = new ExponentiallyModifiedGaussianDistribution(mean, stdDev, lambda);
System.out.println(sampleStdDev);
System.out.println(exGaussian.getStddev());
Gradle 依赖关系:
compile group: 'de.lmu.ifi.dbs.elki', name: 'elki', version: '0.7.1'
compile group: 'org.apache.commons', name: 'commons-math3', version:
'3.6'
ELKI 包含分布的各种 估计器 (请注意,对于某些分布,我们有多种估计技术;而对于某些我们还没有 - 请 贡献!):
ExponentiallyModifiedGaussianDistribution dist =
EMGOlivierNorbergEstimator.STATIC.estimate(dataPoints, DoubleArrayAdapter.STATIC);
将产生 ExGaussian 分布:
> ExGaussianDistribution(mean=0.2675761092764285, stddev=0.07999178722695827,
lambda=4.4179732613344)
您也可以尝试最佳拟合估计。
Distribution dist = BestFitEstimator.STATIC.estimate(dataPoints, DoubleArrayAdapter.STATIC);
这表明移位的对数正态分布可能更适合您的数据(但尽管如此,理论上 EMG 可能更适合您的问题 - 移位的对数正态分布总是有点奇怪)。
> LogNormalDistribution(logmean=-1.945322593396174, logstddev=0.968522285758599,
shift=0.2654438504801123)
如何使用 JAVA/Android estimate/fit 指数修正高斯分布 (exGaussian) 的参数?
我需要如下伪代码:
// some observed data points
double dataPoints[] = {200,300,400,278,366,466,325,335,322,332};
// ex-gaussian distribution
ExponentiallyModifiedGaussianDistribution exGaussian = new ExponentiallyModifiedGaussianDistribution();
// MLE
MaximumLikelihoodEstimation MLE = new MaximumLikelihoodEstimation(dataPoints, exGaussian);
MLE.setGuess(3.0, 1.0, 1.0);
MLE.compute();
// get estimated / fitted parameters
double[] parameterEstimates = MLE.getEstimates();
有一些示例演示了 Gamma Distribution 的参数估计。但是这个lib好像没有开源。
而且我在 JAVA 中找到了一个 ex-gaussian distribution implementation。但是缺少参数估计。
我认为有很多方法可以估计参数,例如使用 最大似然估计 (MLE) 等
更新 1:
我会避免使用 less than 40 dataPoints。
更新二:
估计分布参数的一种简单替代方法是矩估计法 (described on wiki)
也许您可以在 stats.stackexchange.com 上得到更好的答案。
但我认为您可以创建一个进行矩匹配的优化算法。基本上你需要最小化样本数据和理论分布之间的第一矩(均值)、第二矩(方差)、第三矩(偏度)等的差异。
您可以将 objective 函数视为矩的和或乘积。您还可以对时刻使用不同的权重(均值获得更高的权重)。
求objective函数的导数可以尝试使用梯度下降法(使用Mathematica或Sage math),甚至可以使用有限差分法对导数进行数值计算。这种方法大量用于估计回归、逻辑回归和人工神经网络的参数。
您还可以使用元启发式算法(遗传、禁忌搜索等)。
估计分布参数的一种简单替代方法是矩量法 (described on wiki)。
实施:
// some observed data points
double dataPoints[] = {0.464,0.443,0.424,0.386,0.367,0.382,0.455,0.410,0.411,0.424,0.338,0.355,0.342,0.324,
0.354,0.322,0.364,0.375,1.085,0.575,0.597,0.464,0.414,0.408,1.156,0.819,1.156,1.024,1.152,1.103,
0.431,0.378,0.358,0.382,0.354,0.435,0.386,0.361,0.397,0.362,0.334,0.357,0.344,0.362,0.317,0.331,
0.199,0.351,0.284,0.343,0.354,0.336,0.280,0.312,0.778,0.723,0.755,0.774,0.759,0.762,0.490,0.400,
0.364,0.439,0.441,0.673};
DescriptiveStatistics maths = new DescriptiveStatistics(dataPoints);
double sampleMean = maths.getMean();
double sampleStdDev = maths.getStandardDeviation();
double sampleSkev = (Math.abs(sampleMean - maths.getPercentile(50)) / sampleStdDev);
// parameter estimation using method of moments ex-gaussian distribution
double mean = sampleMean - sampleStdDev * Math.pow(sampleSkev/2., 1./3) ;
double stdDev = Math.sqrt(sampleStdDev*(1 - Math.pow(sampleSkev/2., 2./3)));
double tau = sampleStdDev * (Math.pow(sampleSkev/2., 1./3));
double lambda = 1 / tau;
ExponentiallyModifiedGaussianDistribution exGaussian = new ExponentiallyModifiedGaussianDistribution(mean, stdDev, lambda);
System.out.println(sampleStdDev);
System.out.println(exGaussian.getStddev());
Gradle 依赖关系:
compile group: 'de.lmu.ifi.dbs.elki', name: 'elki', version: '0.7.1'
compile group: 'org.apache.commons', name: 'commons-math3', version: '3.6'
ELKI 包含分布的各种 估计器 (请注意,对于某些分布,我们有多种估计技术;而对于某些我们还没有 - 请 贡献!):
ExponentiallyModifiedGaussianDistribution dist =
EMGOlivierNorbergEstimator.STATIC.estimate(dataPoints, DoubleArrayAdapter.STATIC);
将产生 ExGaussian 分布:
> ExGaussianDistribution(mean=0.2675761092764285, stddev=0.07999178722695827,
lambda=4.4179732613344)
您也可以尝试最佳拟合估计。
Distribution dist = BestFitEstimator.STATIC.estimate(dataPoints, DoubleArrayAdapter.STATIC);
这表明移位的对数正态分布可能更适合您的数据(但尽管如此,理论上 EMG 可能更适合您的问题 - 移位的对数正态分布总是有点奇怪)。
> LogNormalDistribution(logmean=-1.945322593396174, logstddev=0.968522285758599,
shift=0.2654438504801123)