Java实现最小二乘法的详解

Java实现最小二乘法的详解

在数据分析和预测领域,最小二乘法(Least Squares Method)是一种广泛使用的数学优化技术。它通过最小化预测值与实际观察值之间的差值的平方来找出最佳函数关系。在Java中,我们可以通过编写一个简单的程序来实现最小二乘法。今天,我们就来看一下如何在Java中实现最小二乘法。

首先,我们需要理解最小二乘法的基本概念和计算公式。最小二乘法的核心思想是使用平方误差的和来度量模型的好坏,即求解下面的最小化问题:

min ∑(yi – f(xi))^2

其中,yi是实际观察值,f(xi)是预测值,通过调整函数f(xi)的参数来使得平方误差的和最小。

假设我们要找的函数关系是一次线性关系,即f(x) = ax + b,那么我们可以通过最小二乘法来求解参数a和b的值。这个问题的解可以通过解下列方程组得到:

a∑(xi^2) + b∑xi = ∑xi*yi,a∑xi + bn = ∑yi

其中,n是数据点的数量,∑表示求和。

下面是一个简单的Java程序,实现了最小二乘法的计算过程:

工具类

/**
     * 趋势线筛选数据
     *
     * @param dataPoints 数据
     * @param tolerance  容差
     * @return 趋势数据
     */
    public static List<Map<Double, Double>> calculateTrendLine(List<Double> dataPoints, double tolerance) {
        List<Map<Double, Double>> res = new ArrayList<>();
        if (CollUtil.isEmpty(dataPoints)) {
            throw new RuntimeException("数据不存在");
        }

        double sumX = 0;
        double sumY = 0;
        double sumXX = 0;
        double sumXY = 0;
        int n = dataPoints.size();

        for (int i = 0; i < n; i++) {
            double x = i + 1; // Assuming x values are 1, 2, 3, ...
            double y = dataPoints.get(i);
            sumX += NumberUtil.add(x, sumX);
            sumY += NumberUtil.add(y, sumY);
            sumXX += NumberUtil.mul(x, x);
            sumXY += NumberUtil.mul(x, y);
        }

        double meanX = NumberUtil.div(sumX, n, 2);
        double meanY = NumberUtil.div(sumY, n, 2);

        double slope = NumberUtil.div((sumXY - NumberUtil.mul(n, meanX, meanY).doubleValue()), (sumXX - NumberUtil.mul(n, meanX, meanX).doubleValue()), 2);
        double intercept = NumberUtil.sub(meanY, NumberUtil.mul(slope, meanX));
        for (int i = 0; i < n; i++) {
            double x = i + 1;
            double y = dataPoints.get(i);

            double predictedY = NumberUtil.add(NumberUtil.mul(slope, x), intercept);
            double deviation = NumberUtil.sub(y, predictedY);
            System.out.println("斜率:" + slope);
            System.out.println("截距:" + predictedY);
            log.info("数据:{},斜率:{},截距:{},容差:{}", y, slope, predictedY, deviation);
            if (deviation > tolerance) {
                Map<Double, Double> map = new HashMap<>();
                map.put(y, deviation);
                res.add(map);
            }
        }
        return res;
    }

测试

@Test
    public void test(){
        List<Double> data = new ArrayList<>();
        data.add(1.2);
        data.add(2.4);
        data.add(2.2);
        data.add(3.6);
        data.add(4.8);
        data.add(6.0);
        List<Map<Double,Double>> filteredData = MathUtils.calculateTrendLine(data, reservedPositions);
        System.out.println(filteredData);
    }

20231124113539194-image

20231124113604935-image

 

THE END
喜欢就支持一下吧
点赞7 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容