最小二乘法介绍

最小二乘法(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

 

用C#实现最小二乘法(用OxyPlot绘图)✨的更多相关文章

  1. 这些.NET开源项目你知道吗?让.NET开源来得更加猛烈些吧

    注意:有网友提出部分项目停止更新的事情,这个问题我特意注意过,很多都是小功能组件,功能稳定,没有bug,没更新是正常的.够用就行了.其次技术支持的事情,对开源免费来说,不能太强求,这里发布的都是小功能 ...

  2. C#.NET开源项目、机器学习、商务智能

    所以原谅我,不能把所有的都发上来,太杂了,反而不好. 1..NET时间周期处理组件 这个组件很小,主要是对时间日期,特别是处理时间间隔以及时间范围非常方便.虽然.NET自带了时间日期的部分功能,但可能 ...

  3. 机器学习:R语言中如何使用最小二乘法

    详细内容见上一篇文章:http://www.cnblogs.com/lc1217/p/6514734.html 这里只是介绍下R语言中如何使用最小二乘法解决一次函数的线性回归问题. 代码如下:(数据同 ...

  4. 机器学习:Python中如何使用最小二乘法

    之所以说"使用"而不是"实现",是因为python的相关类库已经帮我们实现了具体算法,而我们只要学会使用就可以了.随着对技术的逐渐掌握及积累,当类库中的算法已经 ...

  5. 机器学习:scipy和sklearn中普通最小二乘法与多项式回归的使用对

    相关内容连接: 机器学习:Python中如何使用最小二乘法(以下简称文一) 机器学习:形如抛物线的散点图在python和R中的非线性回归拟合方法(以下简称文二) 有些内容已经在上面两篇博文中提到了,所 ...

  6. Mathematica/偏导数/最小二乘法(线性回归)

    a = / a //输出的还是2/123 N[a] //输出的就是小数点 N[a,] //保留三位小数点 Clear[a] Solve[== x^- , x] //结果-3 和 3 Plot[Sin[ ...

  7. 最小二乘法 及python 实现

    参考   最小二乘法小结     机器学习:Python 中如何使用最小二乘法 什么是” 最小二乘法” 呢 定义:最小二乘法(又称最小平方法)是一种数学优化技术,它通过最小化误差的平方和寻找数据的最佳 ...

  8. 转悠望南山 Python闲谈(二)聊聊最小二乘法以及leastsq函数

      1 最小二乘法概述 自从开始做毕设以来,发现自己无时无刻不在接触最小二乘法.从求解线性透视图中的消失点,m元n次函数的拟合,包括后来学到的神经网络,其思想归根结底全都是最小二乘法. 1-1 “多线 ...

  9. Python闲谈(二)聊聊最小二乘法以及leastsq函数

    1 最小二乘法概述 自从开始做毕设以来,发现自己无时无刻不在接触最小二乘法.从求解线性透视图中的消失点,m元n次函数的拟合,包括后来学到的神经网络,其思想归根结底全都是最小二乘法. 1-1 “多线→一 ...

  10. C#使用Oxyplot绘制监控界面

    C#中可选的绘图工具有很多,除了Oxyplot还有DynamicDataDisplay(已经改名为InteractiveDataDisplay)等等.不过由于笔者这里存在一些环境上的特殊要求,.Net ...

随机推荐

  1. 寻找市场中的Alpha—WorldQuant的阿尔法设计理念(上)

    本文旨在向读者介绍Alpha的相关基本概念,以及寻找和检验Alpha的主要流程和方法.在上篇中我们梳理了 WorldQuant经典读本FindingAlphas的概要以及WebSim的使用,在下篇中我 ...

  2. 华企盾DSC使用outlook发送加密文件提示解密插件未加载

    1.如果是非exchange邮箱,不能勾选"启用邮件白名单outlook插件(exchange邮箱建议勾选)"​ 2.如果是exchange邮箱则需要勾选"启用邮件白名单 ...

  3. Tomcat自动化脚本

    /bin/bash war包名称 war_name="tchg.war" 要上传war包指定目录 war_dir="/usr/local/src/tchg" 工 ...

  4. 学一点关于JVM类加载的知识

    要研究类加载过程,我们先要知道关于 Java 处理代码的流程是怎么样的. 第一步:编写源代码 这一步是我们最熟悉的,就是我们在 idea 上写的业务代码,生成 Example.java 文件. pub ...

  5. 工具类图片转base64

    工具类图片转base64 import sun.misc.BASE64Encoder; import java.io.FileInputStream; import java.io.IOExcepti ...

  6. Fiddler使用 抓取手机数据包及中文乱码解决方案

    https://blog.csdn.net/zyb2017/article/details/79260086

  7. ORA-28579 在从外部过程代理程序回调时,发生网络错误,ORA-06512 在"SDE.ST_GEOMETRY_SHAPELIB_PKG"

    如图所示,在执行sde.st_transform方法时报错. 环境是arcgis10.8  oracle是12C,版本号是v12.1.0.2.0 但是执行ST_GEOMETRY方法是可以的,说明配置没 ...

  8. 如何实现gif格式图片倒放效果?

    不知道大家看电影的时候有没有发现出现过这样的一个神奇场景: 一个子弹竟然从远处飞回到手枪中,整个场景呈现一种时空倒流的感觉? 正文 先来几个有趣的倒放动图娱乐一下~ 猫:我谢谢你们全家 萌娃快乐针 尊 ...

  9. HDU 4641 K string 后缀自动机

    原题链接 题意 每个测试点,一开始给我们n,m,k然后是一个长度为n的字符串. 之后m次操作,1 c是往字符串后面添加一个字符c,2是查询字符串中出现k次以及以上的子串个数,m为2e5 思路 首先可以 ...

  10. JQuery&Ajax基础知识

    JQuery&Ajax基础知识 1.Jquery简介 Query是一个快速.简洁的JavaScript框架,是继Prototype之后又一个优秀的JavaScript代码库(框架)于2006年 ...