Java代码使用最小二乘法实现线性回归预测

Posted 洛阳泰山

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java代码使用最小二乘法实现线性回归预测相关的知识,希望对你有一定的参考价值。

最小二乘法

简介

最小二乘法是一种在误差估计、不确定度、系统辨识及预测、预报等数据处理诸多学科领域得到广泛应用的数学工具。

它通过最小化误差(真实目标对象与拟合目标对象的差)的平方和寻找数据的最佳函数匹配。利用最小二乘法可以简便地求得未知的数据,并使得这些求得的数据与实际数据之间误差的平方和为最小。

  • 最小二乘法还可用于曲线拟合。对于平面中的这n个点,可以使用无数条曲线来拟合。要求样本回归函数尽可能好地拟合这组值。综合起来看,这条直线处于样本数据的中心位置最合理。选择最佳拟合曲线的标准可以确定为:使总的拟合误差(即总残差)达到最小

  • 最小二乘法也是一种优化方法,求得目标函数的最优值。并且也可以用于曲线拟合,来解决回归问题。回归学习最常用的损失函数是平方损失函数,在此情况下,回归问题可以著名的最小二乘法来解决。

简而言之,最小二乘法同梯度下降类似,都是一种求解无约束最优化问题的常用方法,并且也可以用于曲线拟合,来解决回归问题。

图解

最小二乘求解,即给定一组x和y的样本数据,计算出一条斜线,距离每个样本的y的距离的平均值最小,如下图(这个以水平线为例):

公式

普通最小二乘法一般形式可以写成(字母盖小帽表示估计值,具体参考应用概率统计):

即:

代码


import java.util.HashMap;
import java.util.Map;

/**
 *  线性回归
 * @author tarzan
 */
public class LineRegression 

    /** 直线斜率 */
    private static double k;
    /** 截距 */
    private static double b;
    /**
     * 最小二乘法
     * @param xs
     * @param ys
     * @return y = kx + b, r
     */
    public Map<String, Double> leastSquareMethod(double[] xs, double[] ys) 
        if(0 == xs.length || 0 == ys.length || xs.length != ys.length) 
            throw new RuntimeException();
        
        // x平方差和
        double Sx2 = varianceSum(xs);
        // y平方差和
        double Sy2 = varianceSum(ys);
        // xy协方差和
        double Sxy = covarianceSum(xs, ys);

        double xAvg = arraySum(xs) / xs.length;
        double yAvg = arraySum(ys) / ys.length;

         k = Sxy / Sx2;
         b = yAvg - k * xAvg;
        //拟合度
        double r = Sxy / Math.sqrt(Sx2 * Sy2);
        Map<String, Double> result = new HashMap<>(5);
        result.put("k", k);
        result.put("b", b);
       result.put("r", r);
        return result;
    

    /**
     * 根据x值预测y值
     *
     * @param x x值
     * @return y值
     */
    public double getY(double x) 
        return k*x+b;
    

    /**
     * 根据y值预测x值
     *
     * @param y y值
     * @return x值
     */
    public double getX(double y) 
        return (y-b)/k;
    


    /**
     * 计算方差和
     * @param xs
     * @return
     */
    private double varianceSum(double[] xs) 
        double xAvg = arraySum(xs) / xs.length;
        return arraySqSum(arrayMinus(xs, xAvg));
    

    /**
     * 计算协方差和
     * @param xs
     * @param ys
     * @return
     */
    private double covarianceSum(double[] xs, double[] ys) 
        double xAvg = arraySum(xs) / xs.length;
        double yAvg = arraySum(ys) / ys.length;
        return arrayMulSum(arrayMinus(xs, xAvg), arrayMinus(ys, yAvg));
    

    /**
     * 数组减常数
     * @param xs
     * @param x
     * @return
     */
    private double[] arrayMinus(double[] xs, double x) 
        int n = xs.length;
        double[] result = new double[n];
        for(int i = 0; i < n; i++) 
            result[i] = xs[i] - x;
        
        return result;
    

    /**
     * 数组求和
     * @param xs
     * @return
     */
    private double arraySum(double[] xs) 
        double s = 0 ;
        for( double x : xs ) 
            s = s + x ;
        
        return s ;
    

    /**
     * 数组平方求和
     * @param xs
     * @return
     */
    private double arraySqSum(double[] xs) 
        double s = 0 ;
        for( double x : xs ) 
            s = s + Math.pow(x, 2);
        
        return s ;
    

    /**
     * 数组对应元素相乘求和
     * @param xs
     * @return
     */
    private double arrayMulSum(double[] xs, double[] ys) 
        double s = 0 ;
        for( int i = 0 ; i < xs.length ; i++ )
            s = s + xs[i] * ys[i] ;
        
        return s ;
    

    public static void main(String[] args) 
        double[] xData = new double[]1, 2, 3, 4,5,6,7,8,9,10,11,12;
        double[] yData = new double[]4200,4300,4000,4400,5000,4700,5300,4900,5400,5700,6300,6000;
        LineRegression lineRegression= new LineRegression();
        System.out.println(lineRegression.leastSquareMethod(xData, yData)); 
        //预测
        System.out.println(lineRegression.getY(10d));
    

代码中的k为线性直线的斜率,b为截距,r代表计算结果的直线拟合度。

当r = 1时称为完美拟合,当r =0 时称为糟糕拟合,

  • 事实上,R2不因y 或x 的单位变化而变化。

  • 零条件均值,指给定解释变量的任何值,误差的期望值为零。换言之,即 E(u|x)=0。

测试

idea中运行上面代码的主方法,控制台输出为:

r的值接近于1,说明拟合度高。 测试x=10 时,输出结果5689.7与真实值误差约为11。

最小二乘法线性回测,常用股票、公司未来营收的预测。有着广泛的应用。

文章还有没讲清楚的地方,或为你有疑问的地方,欢迎评论区留言!!!

以上是关于Java代码使用最小二乘法实现线性回归预测的主要内容,如果未能解决你的问题,请参考以下文章

01_有监督学习--简单线性回归模型(最小二乘法代码实现)

r语言如何最小二乘线性回归分析

最小二乘法学习(分享自其他博主)

机器学习模型和算法

最小二乘法的多元线性回归

偏最小二乘法的岭回归分析