C# | 线性回归算法的实现,只需采集少量数据点,即可拟合整个数据集

简介: 什么是线性回归呢?简单来说,线性回归是一种用于建立两个变量之间线性关系的统计方法。在我们的软件开发中,线性回归可以应用于数据分析、预测和优化等领域。什么情况下会用到线性回归呢?线性回归可以用于探索数据之间的关系,可以用于预测未来的趋势。通过少量的数据点就能得到一个可以代表整个数据集的模型。换句话说,只需要采集少量的数据点,就可以拟合出整个数据集。

image.png

C#线性回归算法的实现

@[toc]

前言

  1. 什么是线性回归呢?
    简单来说,线性回归是一种用于建立两个变量之间线性关系的统计方法。在我们的软件开发中,线性回归可以应用于数据分析、预测和优化等领域。

  2. 什么情况下会用到线性回归呢?
    线性回归可以用于探索数据之间的关系,可以用于预测未来的趋势。通过少量的数据点就能得到一个可以代表整个数据集的模型。换句话说,只需要采集少量的数据点,就可以拟合出整个数据集。

示例代码

现在让我们来看一下示例代码:

    /// <summary>
    /// 线性回归类,用于计算一组二维坐标点的线性回归方程(y = kx + b)
    /// </summary>
    public class LinearRegression
    {
   
   
        /// <summary>
        /// 直线斜率
        /// </summary>
        public double Slope {
   
    get; }

        /// <summary>
        /// 直线截距
        /// </summary>
        public double Intercept {
   
    get; }

        /// <summary>
        /// 构造线性回归对象
        /// </summary>
        /// <param name="data">一组坐标点</param>
        /// <exception cref="ArgumentException">当数据为空或数据点个数少于2个时抛出异常</exception>
        public LinearRegression(PointF[] data)
        {
   
   
            if (data == null || data.Length < 2)
            {
   
   
                throw new ArgumentException("Data can not be null or the number of data points must be at least 2.");
            }

            double sumX = 0;
            double sumY = 0;
            double sumXY = 0;
            double sumX2 = 0;
            int n = data.Length;

            foreach (PointF point in data)
            {
   
   
                sumX += point.X;
                sumY += point.Y;
                sumXY += point.X * point.Y;
                sumX2 += point.X * point.X;
            }

            double avgX = sumX / n;
            double avgY = sumY / n;

            Slope = (n * sumXY - sumX * sumY) / (n * sumX2 - sumX * sumX);
            Intercept = avgY - Slope * avgX;
        }

        /// <summary>
        /// 根据 x 坐标计算对应的 y 坐标
        /// </summary>
        /// <param name="x">x 坐标</param>
        /// <returns>y 坐标</returns>
        public double GetY(double x)
        {
   
   
            return Slope * x + Intercept;
        }

        /// <summary>
        /// 根据 y 坐标计算对应的 x 坐标
        /// </summary>
        /// <param name="y">y 坐标</param>
        /// <returns>x 坐标</returns>
        public double GetX(double y)
        {
   
   
            return (y - Intercept) / Slope;
        }
    }

我们定义了一个名为LinearRegression的类。这个类有两个公共属性,分别代表线性回归的斜率截距。我们还定义了一个构造函数,它接受一个PointF类型的数组作为输入,用于计算斜率和截距。

此外还定义了两个方法,分别用于根据x坐标计算对应的y坐标根据y坐标计算对应的x坐标

实现思路

线性回归算法的思路是这样的:

  1. 对于输入的数据点数组,我们首先计算出它们的平均值。
  2. 计算每个数据点与平均值的差值,并将这些差值乘以对应的x和y坐标。
  3. 我们将这些乘积相加并除以对应的坐标的平方和,即可得到斜率。
  4. 通过平均值和斜率的计算结果得出截距。

下面,让我们来看一下重要的代码段:

double sumX = 0;
double sumY = 0;
double sumXY = 0;
double sumX2 = 0;
int n = data.Length;

foreach (PointF point in data)
{
   
   
    sumX += point.X;
    sumY += point.Y;
    sumXY += point.X * point.Y;
    sumX2 += point.X * point.X;
}

double avgX = sumX / n;
double avgY = sumY / n;

Slope = (n * sumXY - sumX * sumY) / (n * sumX2 - sumX * sumX);
Intercept = avgY - Slope * avgX;

通过foreach循环遍历每一个数据点,并计算出所有需要的变量。接着,我们计算出斜率和截距,并将其分别赋值给类的属性。最后,我们就可以使用GetY和GetX方法来计算任意坐标对应的值了。

测试结果

编写测试代码如下:

    [TestClass]
    public class LinearRegressionTests
    {
   
   
        [TestMethod]
        public void TestLinearRegression()
        {
   
   
            // 构造测试数据
            PointF[] data = new PointF[5]
            {
   
   
                new PointF(1, 1),
                new PointF(2, 3),
                new PointF(3, 5),
                new PointF(4, 7),
                new PointF(5, 9)
            };

            // 构造线性回归对象
            LinearRegression lr = new LinearRegression(data);

            // 验证直线斜率和截距是否正确
            Assert.AreEqual(2, lr.Slope, 0.0001);
            Assert.AreEqual(-1, lr.Intercept, 0.0001);

            // 验证 GetY 方法是否正确计算 y 值
            Assert.AreEqual(1, lr.GetY(1), 0.0001);
            Assert.AreEqual(3, lr.GetY(2), 0.0001);
            Assert.AreEqual(5, lr.GetY(3), 0.0001);
            Assert.AreEqual(7, lr.GetY(4), 0.0001);
            Assert.AreEqual(9, lr.GetY(5), 0.0001);

            // 验证 GetX 方法是否正确计算 x 值
            Assert.AreEqual(1, lr.GetX(1), 0.0001);
            Assert.AreEqual(2, lr.GetX(3), 0.0001);
            Assert.AreEqual(3, lr.GetX(5), 0.0001);
            Assert.AreEqual(4, lr.GetX(7), 0.0001);
            Assert.AreEqual(5, lr.GetX(9), 0.0001);
        }
    }

测试结果:
image.png


结束语

通过本章的代码可以轻松实现线性回归算法。如果您觉得本文对您有所帮助,请不要吝啬您的点赞和评论,提供宝贵的反馈和建议,让更多的读者受益。

相关文章
|
27天前
|
机器学习/深度学习 算法 数据挖掘
K-means聚类算法是机器学习中常用的一种聚类方法,通过将数据集划分为K个簇来简化数据结构
K-means聚类算法是机器学习中常用的一种聚类方法,通过将数据集划分为K个簇来简化数据结构。本文介绍了K-means算法的基本原理,包括初始化、数据点分配与簇中心更新等步骤,以及如何在Python中实现该算法,最后讨论了其优缺点及应用场景。
88 4
|
1月前
|
机器学习/深度学习 自然语言处理 算法
深入理解机器学习算法:从线性回归到神经网络
深入理解机器学习算法:从线性回归到神经网络
|
1月前
|
存储 编解码 负载均衡
数据分片算法
【10月更文挑战第25天】不同的数据分片算法适用于不同的应用场景和数据特点,在实际应用中,需要根据具体的业务需求、数据分布情况、系统性能要求等因素综合考虑,选择合适的数据分片算法,以实现数据的高效存储、查询和处理。
|
1月前
|
存储 缓存 算法
分布式缓存有哪些常用的数据分片算法?
【10月更文挑战第25天】在实际应用中,需要根据具体的业务需求、数据特征以及系统的可扩展性要求等因素综合考虑,选择合适的数据分片算法,以实现分布式缓存的高效运行和数据的合理分布。
|
2月前
|
机器学习/深度学习 人工智能 算法
"拥抱AI规模化浪潮:从数据到算法,解锁未来无限可能,你准备好迎接这场技术革命了吗?"
【10月更文挑战第14天】本文探讨了AI规模化的重要性和挑战,涵盖数据、算法、算力和应用场景等方面。通过使用Python和TensorFlow的示例代码,展示了如何训练并应用一个基本的AI模型进行图像分类,强调了AI规模化在各行业的广泛应用前景。
37 5
|
1月前
|
存储 JSON 算法
TDengine 检测数据最佳压缩算法工具,助你一键找出最优压缩方案
在使用 TDengine 存储时序数据时,压缩数据以节省磁盘空间是至关重要的。TDengine 支持用户根据自身数据特性灵活指定压缩算法,从而实现更高效的存储。然而,如何选择最合适的压缩算法,才能最大限度地降低存储开销?为了解决这一问题,我们特别推出了一个实用工具,帮助用户快速判断并选择最适合其数据特征的压缩算法。
55 0
|
2月前
|
人工智能 算法 前端开发
无界批发零售定义及无界AI算法,打破传统壁垒,累积数据流量
“无界批发与零售”是一种结合了批发与零售的商业模式,通过后端逻辑、数据库设计和前端用户界面实现。该模式支持用户注册、登录、商品管理、订单处理、批发与零售功能,并根据用户行为计算信用等级,确保交易安全与高效。
|
2月前
|
前端开发 算法 JavaScript
无界SaaS模式深度解析:算力算法、链接力、数据确权制度
私域电商的无界SaaS模式涉及后端开发、前端开发、数据库设计、API接口、区块链技术、支付和身份验证系统等多个技术领域。本文通过简化框架和示例代码,指导如何将核心功能转化为技术实现,涵盖用户管理、企业店铺管理、数据流量管理等关键环节。
|
1月前
|
C# 开发者
C# 一分钟浅谈:Code Contracts 与契约编程
【10月更文挑战第26天】本文介绍了 C# 中的 Code Contracts,这是一个强大的工具,用于通过契约编程增强代码的健壮性和可维护性。文章从基本概念入手,详细讲解了前置条件、后置条件和对象不变量的使用方法,并通过具体代码示例进行了说明。同时,文章还探讨了常见的问题和易错点,如忘记启用静态检查、过度依赖契约和性能影响,并提供了相应的解决建议。希望读者能通过本文更好地理解和应用 Code Contracts。
36 3
|
3天前
|
存储 安全 编译器
学懂C#编程:属性(Property)的概念定义及使用详解
通过深入理解和使用C#的属性,可以编写更清晰、简洁和高效的代码,为开发高质量的应用程序奠定基础。
31 12