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

在这里插入图片描述

C#线性回归算法的实现

文章目录

  • C#线性回归算法的实现
    • 前言
    • 示例代码
    • 实现思路
    • 测试结果
    • 结束语

前言

  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);
        }
    }

测试结果:
在这里插入图片描述


结束语

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/25822.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

计算机组成原理-指令系统-机器级语言表示(汇编)

目录 一、X86汇编语言指令基础 寄存器 常见的算数运算指令​编辑 常见逻辑运算指令 AT&T格式和 Intel格式指令 选择语句的机器级表示 循环语句的机器级表示 二、CISC和RISC 一、X86汇编语言指令基础 寄存器 常见的算数运算指令 常见逻辑运算指令 AT&T格式和 Intel格…

使用Python将《青花瓷》歌词生成词云图

哈喽大家好&#xff0c;因为上次有小伙伴问我&#xff0c;歌曲的歌词和评论怎么生成词云图&#xff0c;想买代码… 当时我就拒绝了&#xff0c;直接免费送给了他。 所以今天来分享给大家 我们以周董的《青花瓷》为例&#xff0c;要对《青花瓷》歌词生成词云图&#xff0c;需…

代码创作世界——pytorch深度学习框架数据类型

代码创作世界——pytorch深度学习框架数据类型 torch中的数据类型张量&#xff08;tensor&#xff09; pytorch中的 在数学中&#xff0c;一个单独的数可以成为标量&#xff0c;一行或者一列数组可以称为向量&#xff0c;一个二维数组称为一个矩阵&#xff0c;矩阵中的每一个元…

市值蒸发21亿港元,王一博还能拉着乐华走多久?

5月22日&#xff0c;#乐华被冻结2390万财产#话题冲上热搜。 近日&#xff0c;头顶“王一博”光环的乐华娱乐集团&#xff08;下称“乐华娱乐”&#xff0c;02306.HK&#xff09;交出了上市后的首份财报。 4月25日&#xff0c;财报公布的首个交易日&#xff0c;其股价下跌2.06…

商代数与积代数

商代数 设 R R R使 A < S , ∗ 1 , ∗ 2 , ⋯ , ∗ n > A \left<S, *_1, *_2,\cdots, *_n\right> A⟨S,∗1​,∗2​,⋯,∗n​⟩上的同余关系&#xff0c;则 R R R使 S S S上的等价关系&#xff0c;因此 R R R可诱导出 S S S的一个划分 S / R { [ a ] R ∣ a ∈…

【Linux】Linux环境基础工具的基本使用及配置(yum、vim)

​ ​&#x1f4dd;个人主页&#xff1a;Sherry的成长之路 &#x1f3e0;学习社区&#xff1a;Sherry的成长之路&#xff08;个人社区&#xff09; &#x1f4d6;专栏链接&#xff1a;Linux &#x1f3af;长路漫漫浩浩&#xff0c;万事皆有期待 文章目录 Linux软件包管理器 - y…

【深入浅出Spring Security(二)】Spring Security的实现原理

Spring Security的实现原理 一、实现原理二、内置Filter以及默认加载的Filter三、自动配置分析&#xff08;SpringBootWebSecurityConfiguration&#xff09;ConditionalOnMissingBean 四、自己配置SecurityFilterChain 一、实现原理 在 Spring Security 中&#xff0c;认证、…

高压功率放大器ATA4014VS高压功率放大器HSA42014

高压功率放大器ATA4014VS高压功率放大器HSA42014 一、企业背景&#xff1a; Aigtek是一家来自中国的专业从事测量仪器研发、生产和销售的高科技企业。公司主要研发和生产功率放大器、功率放大器模块、功率信号源、计量校准源等产品。核心团队主要是来自西安交通大学及西北工业大…

LiangGaRy-学习笔记-Day17

1、磁盘的介绍 自动分区、手工分区、命令工具分区 1.1、磁盘分类 根据介质来区分&#xff1a; 机械硬盘和固态硬盘 通过盘大小&#xff1a; 3.5英寸和2.5英寸 通过接口分类&#xff1a; SAS、SATA、FC scisi 根据功能&#xff1a; 桌面和企业级别 1.2、磁盘类型 HD…

数据在内存中的存储(1)——整形

目录 1、数据类型介绍 1.1、类型的基本归类 整形家族 浮点数家族 指针类型 空类型 构造类型 2、整形在内存中的存储 2.1、原码、反码、补码 2.2、大小端介绍 2.3、有符号与无符号 2.4、练习 例一 例二 例三 例四 例五 1、数据类型介绍 我们先来简单了解一下我们前面所学的基…

STM32F4_软件模拟SPI

目录 1. 硬件连接 2. SPI通讯协议 3. W25Q64 简介 4. 程序详解 4.1 main.c 4.2 SPI.c 4.3 SPI.h 4.4 W25Q128.c 4.5 W25Q128.h 4.6 OLED.c 4.7 OLED.h 4.8 OLED_Font.h 5. 实验结果 我们都知道&#xff0c;SPI 和 IIC 一样&#xff0c;都可以通过硬件方式和软件方…

Phaser笔记-精灵(sprite)的使用

如下&#xff1a; 使用逻辑如下&#xff1a; ①设置好physics&#xff1b; ②将资源添加到spritesheet&#xff1b; ③在physics中添加sprite&#xff1b; ④创建anims&#xff1b; ⑤播放anims&#xff1b; 完整代码如下&#xff1a; import phaser;class PlayGame exte…

Linux 系统上的库文件生成与使用

1.库文件 库是一组预先编译好的方法的集合。Linux系统存储的库的位置一般在&#xff1a;/lib 和 /usr/lib。 在 64 位的系统上有些库也可能被存储在/usr/lib64 下。库的头文件一般会被存储在 /usr/include 下或其子目录下。 库有两种&#xff0c;一种是静态库&#xff0c;其…

springboot + vue3实现视频播放Demo(video.js Vue3-video-play视频播放器)

文章目录 学习链接前言ffmpeg安装ffmpeg配置环境变量分割视频文件 后台配置WebConfig 前端代码video.js示例安装依赖视频播放组件效果 Vue3-video-play示例安装依赖main.js中使用视频播放组件效果 学习链接 ffmpeg官网 长时长视频java存储及vue播放解决方法 【 攻城略地 】vue…

Packet Tracer - 配置区域策略防火墙

Packet Tracer - 配置区域策略防火墙 拓扑 地址表 设备 接口 IP地址 子网掩码 默认网关 交换机端口 R1 F0/1 192.168.1.1 255.255.255.0 N/A S1 F0/2 S0/3/0 (DCE) 10.1.1.1 255.255.255.252 N/A N/A R2 S0/3/0 10.1.1.2 255.255.255.252 N/A N/A S0/3…

C++ priority_queue

C priority_queue &#x1f4df;作者主页&#xff1a;慢热的陕西人 &#x1f334;专栏链接&#xff1a;C &#x1f4e3;欢迎各位大佬&#x1f44d;点赞&#x1f525;关注&#x1f693;收藏&#xff0c;&#x1f349;留言 本博客主要内容讲解了优先队列的对应接口的使用 文章目录…

[GUET-CTF2019]number_game[数独]

目录 题目 学到的知识点&#xff1a; 题目 在buu上看到了一道数独题&#xff0c;没见过&#xff0c;记录一下 下载附件&#xff0c;查壳&#xff0c;无壳&#xff0c;在IDA中打开&#xff0c;直接找到主函数 unsigned __int64 __fastcall main(int a1, char **a2, char **a3…

工程swift与OC混编改造

最近公司项目准备引入swift&#xff0c;由于目前工程已经完成了组件化不再是简单的单仓工程&#xff0c;所以需要进行混编改造。下面记录一下自己对工程进行混编改造的思考以及过程。 混编原理 看了很多文档&#xff0c;比较少有讲混编原理的&#xff0c;这里简单介绍一下语言…

springboot+springsecurity+jwt+elementui图书管理系统

​​图书管理系统​​ 关注公号&#xff1a;java大师&#xff0c;回复“图书”&#xff0c;获取源码 一、springboot后台 1、mybatis-plus整合 1.1添加pom.xml <!--mp逆向工程 --><dependency><groupId>org.projectlombok</groupId><artifactId&…

子串--子字符串 0528

210102 201012 A1A2…An An…A2A1 如何做&#xff0c; 翻转的是21&#xff0c;因为2>1; 翻转的是210&#xff0c;因为2>0; 翻转的是2101&#xff0c;因为2>1&#xff1b; 翻转的是21010&#xff0c;因为2>0&#xff1b; 翻转的是210102&#xff0c;因为22且1&…