【算法研究与实现】最小二乘法直线拟合

1.原理 

在现实中经常遇到这样的问题,一个函数并不是以某个数学表达式的形式给出,而是以一些自变量与因变量的对应表给出,老师讲课的时候举的个例子是犯罪人的身高和留下的脚印长,可以测出一些人的数据然后得到一张表,它反应的是一个函数,回归的意思就是将它还原成数学表达式,这个式子也称为经验表达式,之所以叫经验就是说它不完全是实际中的那样准确,是有一定偏差的,只是偏差很小罢了。

最小二乘法

设经验

方程是y=F(x),方程中含有一些待定系数an,给出真实值{(xi,yi)|i=1,2,...n},将这些x,y值代入方程然后作

差,可以描述误差:yi-F(xi),为了考虑整体的误差,可以取平方和,之所以要平方是考虑到误差可正可负直接相加可以相互抵消,所以记误差为:

e=∑(yi-F(xi))^2

它是一个多元函数,有an共n个未知量,现在要求的是最小值。所以必然满足对各变量的偏导等于0,于是得到n个方程:

de/da1=0

de/da2=0

...

de/dan=0

n个方程确定n个未知量为常量是理论上可以解出来的。用这种误差分析的方法进行回归方程的方法就是最小二乘法。

线性回归

如果经验方程是线性的,形如y=ax+b,就是线性回归。按上面的分析,误差函数为:

e=∑(yi-axi-b)^2

各偏导为:

de/da=2∑(yi-axi-b)xi=0

de/db=-2∑(yi-axi-b)=0

于是得到关于a,b的线性方程组:

(∑xi^2)a+(∑xi)b=∑yixi

(∑xi)a+nb=∑yi

设A=∑xi^2,B=∑xi,C=∑yixi,D=∑yi,则方程化为:

Aa+Bb=C

Ba+nb=D

解出a,b得:

a=(Cn-BD)/(An-BB)

b=(AD-CB)/(An-BB)

这就是我们要进行的算法。

2.C++实现 

/*

* =====================================================================================

*

*       Filename:  nihe.cpp

*

*    Description:  A least square method for fitting a curve

*

*        Version:  1.0

*        Created:  03/18/2015 12:32:56 PM

*       Revision:  none

*       Compiler:  gcc

*      新浪微博: http://weibo.com/u/1645794700/home?wvr=5&c=spr_web_360_hao360_weibo_t001  CV机器视觉2013

*

*

* =====================================================================================

*/

#include  <stdlib.h>

#include  <iostream>

#include  <valarray>

using namespace std;

int main(int argc, char *argv[])

{

int num = 0;

cout << " Input how many numbers you want to calculate:";

cin >> num;

valarray<double> data_x(num);

valarray<double> data_y(num);

while( num )

{

cout << "Input the "<< num <<" of x:";

cin >> data_x[num-1];

cout << "Input the "<< num <<" of y:";

cin >> data_y[num-1];

num--;

}

double A =0.0;

double B =0.0;

double C =0.0;

double D =0.0;

A = (data_x*data_x).sum();

B = data_x.sum();

C = (data_x*data_y).sum();

D = data_y.sum();

double k,b,tmp =0;

if(tmp=(A*data_x.size()-B*B))

{

k = (C*data_x.size()-B*D)/tmp;

b = (A*D-C*B)/tmp;

}

else

{

k=1;

b=0;

}

cout <<"k="<<k<<endl;

cout <<"b="<<b<<endl;

return 0;

}

3.OpenCV结构实现 

#include "cv.h"

#include <iostream>

using namespace std;

int main(int argc, char *argv[])

{

int i=0;

int j=0;

int num;

double A,B,C,D;

double k,b,tmp=0;

cout <<"Input how many numbers you want to calculate:";

cin >>num;

CvMat *mat1=cvCreateMat(1,num,CV_64FC1);

CvMat *mat2=cvCreateMat(1,num,CV_64FC1);

CvMat *mattmp=cvCreateMat(1,num,CV_64FC1);

for (j=0;j<mat1->cols;j++)

{

cout << "data X"<<j<<"=";

cin>>CV_MAT_ELEM(*mat1,double,0,j);

cout << "data Y"<<j<<"=";

cin>>CV_MAT_ELEM(*mat2,double,0,j);

}

for (j=0;j<mat1->cols;j++)

{

cout<<"X="<<CV_MAT_ELEM(*mat1,double,0,j)

<<",Y="<<CV_MAT_ELEM(*mat2,double,0,j)<<endl;

}

cvMul(mat1,mat1,mattmp,1);

A = cvSum(mattmp).val[0];

B = cvSum(mat1).val[0];

cvMul(mat1,mat2,mattmp,1);

C = cvSum(mattmp).val[0];

D = cvSum(mat2).val[0];

tmp = A*mat1->cols-B*B;

k = (C*mat1->cols-B*D)/tmp;

b = (A*D-C*B)/tmp;

cout << "k=" << k <<endl;

cout << "b=" << b <<endl;

cvReleaseMat(&mat1);

cvReleaseMat(&mat2);

return 0;

}

时间: 2024-08-01 10:20:23

【算法研究与实现】最小二乘法直线拟合的相关文章

最小二乘法直线拟合

最小二乘法的直线拟合 #coding:utf-8 import numpy as np import matplotlib.pyplot as plt dots = np.array([[1,6], [2,5], [3,7], [4,10]]) plt.plot([i[0] for i in dots],      [i[1] for i in dots], 'ro') plt.axis([0, 6, 0, 12]) def nihezhixian(k, x, b):     return k*

直线拟合算法

在计算机视觉的应用中,经常会用到提取一条直线的精确位置这样的工作.这时就要用到直线的拟合算法了. 这里,我也贴一个利用最小二乘法计算最佳拟合直线的代码. 这个代码是我以前学习<机器视觉算法与应用(双语版)>[德] 斯蒂格(Steger C) 著:杨少荣 等 译 的书时写的.所有的公式推导都在书中 3.8.1 ,还算比较有用. 与一元线性回归算法的区别:一元线性回归算法假定 X 是无误差的,只有 Y 有误差. 而这个算法假设每个点的 X Y 坐标的误差都是符合 0 均值的正态分布的. 因此,在计

直线拟合算法(续)

直线拟合算法(续) 曾经写过一篇博客.介绍直线拟合算法. http://blog.csdn.net/liyuanbhu/article/details/50866802 给出的代码事实上有一点小问题,就是 den = 0 时会出现除以 0 的错误. 今天正好也有网友问起这个问题. 我就再写一篇短文来说说怎样解决问题. 首先我们知道: den=D2xy+(λ?Dxx)2??????????????√ 那么 den=0 意味着: Dxy=0λ=Dxx 我们还有关于 λ 的计算式: λ=Dxx+Dyy

ax+by+c=0 型直线拟合算法

所谓直线拟合,通常也叫做线性拟合.一元线性回归.指的是当我们有一批数据(xi,yi),这些数据在平面坐标系下落在一条直线上,或近似的落在一条直线上.我们就要求出这条直线的参数.如果这条直线可以写为: y=kx+b 那么 k=∑(xi?xˉ)(yi?yˉ)∑(xi?xˉ)2 b=yˉ?kxˉ 这个关系式许多教科书上都有详细的推导,无需多说. 今天要说的是另一种情况,当我们的数据有可能落在一条竖直的直线上,也就是k 有可能为∞ 时,应该如何做拟合.这时我们肯定就不能用y=kx+b 了,但是可以将这个

OpenCV fitline直线拟合函数学习

下图是OpenCV官方文档中,对直线拟合函数的详细介绍: fitLine()函数用于,对二维或三维空间中的点集进行直线拟合.共有六个参数: param 1:输入的点集,可以是Mat或者vector<>,可以是二维点集或三维点集. 例如: vector<Point> points; param 2:拟合结果,即一条直线.在二维空间中,直线可以定义为 Vec4f line; 在二维平面中,(line[0],line[1])表示直线的方向向量,(line[2],line[3])表示直线上

最小二乘法椭圆拟合

对平面上的一些点拟合有很多手段,其中椭圆拟合在图像轮廓划分等很多方面都很重要,当然,我们一般还是用最小二乘法来拟合椭圆, 在这里,我实现了两种算法,一种是 http://wenku.baidu.com/link?url=7kIrC8LoOMCtlmAH8yqkpUQfiKwWnVe4EoUJekkQSgQ1qTWfLAuEXTYvYTv7SATGIJYX4IxcTIB94-iO0SpUgztWgx661O2VEOwm_dvoSqO 这篇文章给出的,核心也是最小二乘法,利用gauss消去法解方程组

实用性模型算法研究

数据建模十类算法 1.蒙特卡罗算法2.数据拟合.参数估计.插值等数据处理算法3.线性规划.整数规划.多元规划.二次规划等规划类4.图论算法(最短路.网络流.二分图等算法)5.动态规划.回溯搜索.分治算法.分支定界等计算机算法6.最优化理论的三大非经典算法:模拟退火法.神经网络.遗传算法7.网格算法和穷举法8.连续离散化方法9.数值分析算法10.图象处理算法 以上十类算法开篇. 实用性模型算法研究

OpenCV 学习(直线拟合)

OpenCV 学习(直线拟合) Hough 变换可以提取图像中的直线.但是提取的直线的精度不高.而很多场合下,我们需要精确的估计直线的参数,这时就需要进行直线拟合. 直线拟合的方法很多,比如一元线性回归就是一种最简单的直线拟合方法.但是这种方法不适合用于提取图像中的直线.因为这种算法假设每个数据点的X 坐标是准确的,Y 坐标是带有高斯噪声的.可实际上,图像中的每个数据点的XY 坐标都是带有噪声的. 下面就来讲讲适用于提取图像中直线的直线拟合算法. 一个点 (xi,yi) 到直线的距离用 ri 来

基于霍夫变换的形状检测算法研究与实现(java)

利用Hough变换算法检测形状的检测结果如下如所示: 1.检测直线 2.检测圆形 源代码及论文下载地址如下:基于霍夫变换的形状检测算法研究与实现(源代码及论文)