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

2024-01-30 08:44

本文主要是介绍用C#实现最小二乘法(用OxyPlot绘图),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

最小二乘法介绍✨

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

最小二乘法的原理✨

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

image-20240118105946580

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

平方和的公式如下:

image-20240118110247858

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

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

截距推导出来结果如下:

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

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

最小二乘法推导2

最小二乘法推导3

用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包:

image-20240120100221733

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

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

image-20240120100455351

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

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

使用OxyPlot画散点图✨

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

image-20240120101110294

添加OxyPlot.WindowsForms包:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

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

image-20240120101340414

// 初始化散点图数据
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设置为全局变量。

 // 创建 PlotModelplotModel = new PlotModel(){Title = "散点图"};plotModel.Series.Add(scatterSeries);// 将 PlotModel 设置到 PlotViewplotView1.Model = plotModel;

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

image-20240120102920929

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

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}";}// 刷新 PlotViewplotView1.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的切片语法。

画出来的效果如下所示:

image-20240120103737259

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]));}// 创建 PlotModelplotModel = new PlotModel(){Title = "散点图"};plotModel.Series.Add(scatterSeries);// 将 PlotModel 设置到 PlotViewplotView1.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和cfor(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}";}// 刷新 PlotViewplotView1.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 = 0for 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()

运行效果如下所示:

image-20240120104300224

总结✨

本文向大家介绍了最小二乘法以及公式推导的过程,并使用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

这篇关于用C#实现最小二乘法(用OxyPlot绘图)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/659692

相关文章

C++使用栈实现括号匹配的代码详解

《C++使用栈实现括号匹配的代码详解》在编程中,括号匹配是一个常见问题,尤其是在处理数学表达式、编译器解析等任务时,栈是一种非常适合处理此类问题的数据结构,能够精确地管理括号的匹配问题,本文将通过C+... 目录引言问题描述代码讲解代码解析栈的状态表示测试总结引言在编程中,括号匹配是一个常见问题,尤其是在

Java实现检查多个时间段是否有重合

《Java实现检查多个时间段是否有重合》这篇文章主要为大家详细介绍了如何使用Java实现检查多个时间段是否有重合,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录流程概述步骤详解China编程步骤1:定义时间段类步骤2:添加时间段步骤3:检查时间段是否有重合步骤4:输出结果示例代码结语作

使用C++实现链表元素的反转

《使用C++实现链表元素的反转》反转链表是链表操作中一个经典的问题,也是面试中常见的考题,本文将从思路到实现一步步地讲解如何实现链表的反转,帮助初学者理解这一操作,我们将使用C++代码演示具体实现,同... 目录问题定义思路分析代码实现带头节点的链表代码讲解其他实现方式时间和空间复杂度分析总结问题定义给定

Java覆盖第三方jar包中的某一个类的实现方法

《Java覆盖第三方jar包中的某一个类的实现方法》在我们日常的开发中,经常需要使用第三方的jar包,有时候我们会发现第三方的jar包中的某一个类有问题,或者我们需要定制化修改其中的逻辑,那么应该如何... 目录一、需求描述二、示例描述三、操作步骤四、验证结果五、实现原理一、需求描述需求描述如下:需要在

C#中读取XML文件的四种常用方法

《C#中读取XML文件的四种常用方法》Xml是Internet环境中跨平台的,依赖于内容的技术,是当前处理结构化文档信息的有力工具,下面我们就来看看C#中读取XML文件的方法都有哪些吧... 目录XML简介格式C#读取XML文件方法使用XmlDocument使用XmlTextReader/XmlTextWr

如何使用Java实现请求deepseek

《如何使用Java实现请求deepseek》这篇文章主要为大家详细介绍了如何使用Java实现请求deepseek功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1.deepseek的api创建2.Java实现请求deepseek2.1 pom文件2.2 json转化文件2.2

python使用fastapi实现多语言国际化的操作指南

《python使用fastapi实现多语言国际化的操作指南》本文介绍了使用Python和FastAPI实现多语言国际化的操作指南,包括多语言架构技术栈、翻译管理、前端本地化、语言切换机制以及常见陷阱和... 目录多语言国际化实现指南项目多语言架构技术栈目录结构翻译工作流1. 翻译数据存储2. 翻译生成脚本

如何通过Python实现一个消息队列

《如何通过Python实现一个消息队列》这篇文章主要为大家详细介绍了如何通过Python实现一个简单的消息队列,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录如何通过 python 实现消息队列如何把 http 请求放在队列中执行1. 使用 queue.Queue 和 reque

Python如何实现PDF隐私信息检测

《Python如何实现PDF隐私信息检测》随着越来越多的个人信息以电子形式存储和传输,确保这些信息的安全至关重要,本文将介绍如何使用Python检测PDF文件中的隐私信息,需要的可以参考下... 目录项目背景技术栈代码解析功能说明运行结php果在当今,数据隐私保护变得尤为重要。随着越来越多的个人信息以电子形

使用 sql-research-assistant进行 SQL 数据库研究的实战指南(代码实现演示)

《使用sql-research-assistant进行SQL数据库研究的实战指南(代码实现演示)》本文介绍了sql-research-assistant工具,该工具基于LangChain框架,集... 目录技术背景介绍核心原理解析代码实现演示安装和配置项目集成LangSmith 配置(可选)启动服务应用场景