spring boot根据样本计算正态分布拟合数据

项目需要根据前端输入的样本数据,计算出对应的正态分布拟合曲线,后端使用的是spring boot,所以这里介绍一下Java的实现方式。

1 思路

前端传入对应的上限、下限以及数据样本,后端计算出对应的均值、方差,再根据上下限均分若干份(这里300等份),利用正态分布函数计算出对应的拟合函数值,返回前端渲染。

2 入参

{
  "lsl": 0,
  "sample": [
    {
      "featureValue": 0.1,
      "label": "2023-03-24"
    },
    {
      "featureValue": 0.049,
      "label": "2023-03-23"
    },
    {
      "featureValue": 0.09,
      "label": "2023-03-22"
    },
    {
      "featureValue": 0.08,
      "label": "2023-03-21"
    },
    {
      "featureValue": 0.04,
      "label": "2023-03-20"
    },
    {
      "featureValue": 0.04,
      "label": "2023-03-19"
    }
  ],
  "usl": 0.1
}

其中,usl为控制上限,lsl为控制下限

3 后端拟合

后端接受到数据以后,计算出对应的均值、方差

3.1 均值

不做过多解释

    /**
     * 平均值
     *
     * @param list 样本中的featureValue list
     * @return 
     */
    private Double getMean(List<Double> list) {
        return list.stream().mapToDouble(Double::valueOf).average().orElse(0);
    }

3.2 方差

根据方差公式做计算,公式如下:

σ ^ = ∑ i = 0 n ( x i − x ‾ ) 2 n \hat{\sigma} = \sqrt{\sum_{i = 0} ^n(x_i-\overline{x})^2 \over n} σ^=ni=0n(xix)2

根据以上公式计算即可

    /**
     * Sigma
     *
     * @param list 样本中的featureValue list
     * @param mean 均值
     * @return
     */
    private Double getSigma(List<Double> list, Double mean) {
        return Math.pow(list.stream().mapToDouble(item -> Math.pow(item - mean, 2)).sum() / list.size(), 0.5);
    }

3.2 计算拟合

根据正太分布函数计算,函数如下:

f ( x ) = 1 σ 2 π e − ( x − μ ) 2 2 σ 2 f(x) = {1 \over \sigma\sqrt{2 \pi}}e^{ -{(x-\mu)^2 \over 2\sigma ^ 2}} f(x)=σ2π 1e2σ2(xμ)2

根据这个函数计算即可,即,normalDistribution(double x, double mean, double sigma) 方法

    /**
     * 正太分布拟合曲线
     *
     * @param usl 控制上限
     * @param lsl 控制下限
     * @param mean 均值
     * @param sigma 方差
     * @return
     */
    private List<List<Double>> featureNormal normalDistribution(Double usl, Double lsl, Double mean, Double sigma) {
    	List<List<Double>> featureNormal = new LinkedList<>();
        double normalBegin = Math.min(mean - normalRange / 2, lsl);
        double normalEnd = Math.max(mean + normalRange / 2, usl);
        double normalRange = normalEnd - normalBegin;
        normalBegin = normalBegin - Math.abs(normalBegin * 0.2);
        normalEnd = normalEnd + Math.abs(normalEnd * 0.2);

		//均分300个区间
        Integer normalSize = 300;
        double normalWidth = (normalEnd - normalBegin) / normalSize;
        for (int i = 0; i < normalSize; i++) {
            double x = normalBegin + i * normalWidth;
            featureNormal.add(new LinkedList<>(Lists.newArrayList(x, normalDistribution(x, mean, sigma))));
        }
    }
 
    /**
     * 正太分布拟合值
     *
     * @param x x轴的值
     * @param mean  均值
     * @param sigma 方差
     * @return
     */
    private Double normalDistribution(double x, double mean, double sigma) {
        return (1 / (sigma * Math.sqrt(2 * Math.PI))) * Math.exp(-Math.pow((x - mean), 2) / (2 * Math.pow(sigma, 2)));
    }

由此,便得到了指定区间、指定样本的正态分布拟合曲线,返给前端渲染即可。

3.3 渲染

这里用echarts做了一个简单的渲染
spring boot根据样本计算正态分布拟合数据_第1张图片

你可能感兴趣的:(spring,boot,spring,boot,java,正太分布,正太拟合)