用C#实现最小二乘法(用OxyPlot绘图)

简介: 用C#实现最小二乘法(用OxyPlot绘图)✨

最小二乘法介绍✨

最小二乘法(Least Squares Method)是一种常见的数学优化技术,广泛应用于数据拟合、回归分析和参数估计等领域。其目标是通过最小化残差平方和来找到一组参数,使得模型预测值与观测值之间的差异最小化。

最小二乘法的原理✨

线性回归模型将因变量 (y) 与至少一个自变量 (x) 之间的关系建立为:

在 OLS 方法中,我们必须选择一个b1和b0的值,以便将 y 的实际值和拟合值之间的差值的平方和最小化。

平方和的公式如下:

我们可以把它看成是一个关于b1和b0的函数,分别对b1和b0求偏导,然后让偏导等于0,就可以得到最小平方和对应的b1和b0的值。

先说结果,斜率最后推导出来如下所示:

截距推导出来结果如下:

don't worry about that,慢慢推导总是可以弄明白的(不感兴趣可以直接略过):

用C#实现最小二乘法✨

创建数据点✨

首先创建想要拟合的数据点:

NDArray? x, y;


x,y为全局变量。

 //使用NumSharp创建线性回归的数据集

x = np.arange(0, 10, 0.2);
  y = 2 * x + 3 + np.random.normal(0, 3, x.size);


使用到了NumSharp,需要为项目添加NumSharp包:

x = np.arange(0, 10, 0.2);


的意思是x从0增加到10(不包含10),步长为0.2:

np.random.normal(0, 3, x.size);


的意思是生成了一个均值为0,标准差为3,数量与x数组长度相同的正态分布随机数数组。这个数组被用作线性回归数据的噪声。

使用OxyPlot画散点图✨

OxyPlot是一个用于在.NET应用程序中创建数据可视化图表的开源图表库。它提供了丰富的功能和灵活性,使开发者能够轻松地在其应用程序中集成各种类型的图表,包括折线图、柱状图、饼图等。

添加OxyPlot.WindowsForms包:

将PlotView控件添加到窗体设计器上:

// 初始化散点图数据
var scatterSeries = new ScatterSeries
{
    MarkerType = MarkerType.Circle,
    MarkerSize = 5,
    MarkerFill = OxyColors.Blue
};
表示标志为圆形,标志用蓝色填充,标志的大小为5。
  for (int i = 0; i < x.size; i++)
  {
      scatterSeries.Points.Add(new ScatterPoint(x[i], y[i]));
  }
添加数据点。
 PlotModel? plotModel;
将plotModel设置为全局变量。
 // 创建 PlotModel
 plotModel = new PlotModel()
 {
     Title = "散点图"
 };
 plotModel.Series.Add(scatterSeries);
 // 将 PlotModel 设置到 PlotView
 plotView1.Model = plotModel;


这样就成功绘制了散点图,效果如下所示:

使用最小二乘法拟合数据点✨

double a = 0;
double c = 0;
double x_mean = x?.mean();
double y_mean = y?.mean();
//计算a和c
for(int i = 0; i < x?.size; i++) 
{
    a += (x[i] - x_mean) * (y?[i] - y_mean);
    c += (x[i] - x_mean) * (x[i] - x_mean);
}
//计算斜率和截距
double m = a / c;
double b = y_mean - m * x_mean;
//拟合的直线
var y2 = m * x + b;
套用公式就可以,a表示上面斜率公式的上面那部分,c表示上面斜率公式的下面那部分。
double x_mean = x?.mean();
double y_mean = y?.mean();
计算x与y的平均值。


使用OxyPlot画拟合出来的直线✨

//画这条直线         
 var lineSeries = new LineSeries
 {
     Points = { new DataPoint(x?[0], y2[0]), new DataPoint(x?[-1], y2[-1]) },
     Color = OxyColors.Red
 };
 // 创建 PlotModel         
 plotModel?.Series.Add(lineSeries);
 // 为图表添加标题
 if (plotModel != null)
 {
     plotModel.Title = $"拟合的直线 y = {m:0.00}x + {b:0.00}";
 }
 // 刷新 PlotView
 plotView1.InvalidatePlot(true);
 Points = { new DataPoint(x?[0], y2[0]), new DataPoint(x?[-1], y2[-1]) },


画直线只要添加两个点就好了x?[0], y2[0]表示x和y的第一个点,x?[-1], y2[-1])表示x和y的最后一个点,使用了NumSharp的切片语法。

画出来的效果如下所示:

C#实现的全部代码:

using NumSharp;
using OxyPlot.Series;
using OxyPlot;
namespace OlsRegressionDemoUsingWinform
{
    public partial class Form1 : Form
    {
        NDArray? x, y;
        PlotModel? plotModel;
        public Form1()
        {
            InitializeComponent();
        }
        private void button1_Click(object sender, EventArgs e)
        {
            //使用NumSharp创建线性回归的数据集
            x = np.arange(0, 10, 0.2);
            y = 2 * x + 3 + np.random.normal(0, 3, x.size);
            // 初始化散点图数据
            var scatterSeries = new ScatterSeries
            {
                MarkerType = MarkerType.Circle,
                MarkerSize = 5,
                MarkerFill = OxyColors.Blue
            };
            for (int i = 0; i < x.size; i++)
            {
                scatterSeries.Points.Add(new ScatterPoint(x[i], y[i]));
            }
            // 创建 PlotModel
            plotModel = new PlotModel()
            {
                Title = "散点图"
            };
            plotModel.Series.Add(scatterSeries);
            // 将 PlotModel 设置到 PlotView
            plotView1.Model = plotModel;
        }
        private void button2_Click(object sender, EventArgs e)
        {
            double a = 0;
            double c = 0;
            double x_mean = x?.mean();
            double y_mean = y?.mean();
            //计算a和c
            for(int i = 0; i < x?.size; i++) 
            {
                a += (x[i] - x_mean) * (y?[i] - y_mean);
                c += (x[i] - x_mean) * (x[i] - x_mean);
            }
            //计算斜率和截距
            double m = a / c;
            double b = y_mean - m * x_mean;
            //拟合的直线
            var y2 = m * x + b;
            //画这条直线         
            var lineSeries = new LineSeries
            {
                Points = { new DataPoint(x?[0], y2[0]), new DataPoint(x?[-1], y2[-1]) },
                Color = OxyColors.Red
            };
            // 创建 PlotModel         
            plotModel?.Series.Add(lineSeries);
            // 为图表添加标题
            if (plotModel != null)
            {
                plotModel.Title = $"拟合的直线 y = {m:0.00}x + {b:0.00}";
            }
           
            // 刷新 PlotView
            plotView1.InvalidatePlot(true);
        }
    }
}


用Python实现最小二乘法✨

import numpy as np
import matplotlib.pyplot as plt
# 用最小二乘法拟合 y = mx + b
# 设置随机数种子以保证结果的可复现性
np.random.seed(0)
# 生成一个在[0, 10]区间内均匀分布的100个数作为x
x = np.linspace(0, 10, 100)
# 生成y,y = 2x + 噪声,其中噪声是[0, 10)之间的随机整数
y = 2 * x + 5 + np.random.randint(0, 10, size=100)
# 计算x和y的均值
x_mean = np.mean(x)
y_mean = np.mean(y)
a = 0
c = 0
for i in range(x.shape[0]):
   a += (x[i] - x_mean) * (y[i] - y_mean)
   c += (x[i] - x_mean) ** 2
# 计算斜率和截距
m = a / c
b = y_mean - m * x_mean
   
# 画这条直线
y2 = m * x + b
plt.plot(x, y2, color='red')
# 画数据点
plt.scatter(x, y)
plt.xlabel('x')
plt.ylabel('y')
plt.title(f'y = {m:.2f}x + {b:.2f}')
plt.show()


运行效果如下所示:

总结✨

本文向大家介绍了最小二乘法以及公式推导的过程,并使用C#与Python进行实现。重点介绍了C#中是如何实现的,同时介绍了在C#中如何使用OxyPlot绘图。希望对你有所帮助。

参考✨

1、Understanding Ordinary Least Squares (OLS) Regression | Built In

2、Machine Learning Series-Linear Regression Ordinary Least Square Method - YouTube

 

相关文章
ffmpeg 命令提取音视频数据-ffmpeg导出h265裸流-ffmpeg导出h264裸流
ffmpeg 命令提取音视频数据-ffmpeg导出h265裸流-ffmpeg导出h264裸流
663 0
|
8月前
|
监控 算法 C#
C#与Halcon联合编程实现鼠标控制图像缩放、拖动及ROI绘制
C#与Halcon联合编程实现鼠标控制图像缩放、拖动及ROI绘制
1743 0
|
C# C++
一款.NET开源、功能强大、跨平台的绘图库 - OxyPlot
一款.NET开源、功能强大、跨平台的绘图库 - OxyPlot
316 0
|
C# 数据可视化 开发者
WPF开发者福音:深度解析OxyPlot与LiveCharts图表库,轻松实现数据可视化不再是难题!
【8月更文挑战第31天】在WPF应用中,数据可视化对提升用户体验至关重要。本文介绍并演示了两种流行图表库OxyPlot和LiveCharts的集成与使用方法。OxyPlot是一款适用于.NET应用的开源图表库,提供多种图表类型,易于集成。LiveCharts则以其丰富的图表类型和动画效果,特别适合实时数据展示。通过具体代码示例,本文展示了如何利用这两种图表库创建折线图和柱状图,并详细说明了安装和配置步骤。希望本文能帮助开发者在WPF应用中轻松实现高效、美观的数据可视化。
1957 0
|
数据采集 JSON 开发者
Python爬虫京东商品详情数据接口
京东商品详情数据接口(JD.item_get)提供商品标题、价格、品牌、规格、图片等详细信息,适用于电商数据分析、竞品分析等。开发者需先注册账号、创建应用并申请接口权限,使用时需遵循相关规则,注意数据更新频率和错误处理。示例代码展示了如何通过 Python 调用此接口并处理返回的 JSON 数据。
|
运维 监控 物联网
物联网卡:物联网卡为什么好用
物联网卡(IoT SIM卡)因其独特的特性和广泛的应用场景,成为许多智能设备和物联网解决方案中不可或缺的一部分。以下是物联网卡好用的几个理由:
|
存储 算法 安全
C# | 上位机开发新手指南(五)校验算法——CRC
当我们在进行数据传输时,可能会因为信道噪声、干扰等因素导致数据出现错误,从而影响传输的可靠性和准确性。此时,我们需要一种方法来检测数据是否出现错误,并尽可能快速地发现和纠正错误。CRC(Cyclic Redundancy Check)校验算法就是一种常用的数据校验方法,它通过对数据进行处理生成校验码,从而实现对数据的完整性和准确性进行验证。 使用CRC校验的意义在于能够提高数据传输的可靠性,降低数据传输错误率,确保数据的完整性和准确性。在各个领域中,如通信、网络、存储等,CRC校验都得到了广泛的应用。
1438 0
C# | 上位机开发新手指南(五)校验算法——CRC
|
JavaScript 前端开发
vue导出pdf(大数量可能有问题)
vue导出pdf(大数量可能有问题)
736 2
|
C# Windows
c#学习系列相关之多线程(三)----invoke和begininvoke
c#学习系列相关之多线程(三)----invoke和begininvoke
2088 0
|
PHP UED 开发者
PHP中的异常处理:深入理解try-catch语句
本文将深入探讨PHP中的异常处理机制,特别是try-catch语句的使用。我们将通过实例来理解如何在PHP代码中有效地使用try-catch语句,以及它们在错误处理和程序流程控制中的重要性。

热门文章

最新文章