最小二乘法拟合二维曲线的原理及实现

已知有n个数据点: ( x 1 , y 1 ) , ( x 2 , y 2 ) , … , ( x n , y n ) (x_1, y_1), (x_2, y_2), \ldots, (x_n, y_n) (x1,y1),(x2,y2),,(xn,yn),需要对这n个数据点进行曲线拟合,通过观察发现,它近似于抛物线,假定曲线为: y = a 2 × x 2 + a 1 × x + a 0 y = a_2 ×x^2 + a_1× x +a_0 y=a2×x2+a1×x+a0,其中 a 0 、 a 1 、 a 2 a_0、a_1、a_2 a0a1a2 是未知的,如果把 ( x 1 , y 1 ) (x_1, y_1) (x1,y1)代入方程,得到 y 1 = a 2 × x 1 2 + a 1 × x 1 + a 0 y_1 = a_2× x_1^2 + a_1× x_1 +a_0 y1=a2×x12+a1×x1+a0,然后变形得:
[ x 1 2 x 1 1 ] [ a 2 a 1 a 0 ] = y 1 \begin{gathered} \quad \begin{bmatrix} x_1^2 & x_1 & 1 \end{bmatrix} \begin{bmatrix} a_2 \\ a_1 \\ a_0 \end{bmatrix} = y_1 \end{gathered} [x12x11]a2a1a0=y1
同理,将 ( x i , y i ) , i = 1 , 2 , … , n (x_i, y_i), i = 1, 2, \ldots, n (xi,yi),i=1,2,,n, 代入方程,可以得到:
[ x n 2 x n 1 ] [ a 2 a 1 a 0 ] = y n \begin{gathered} \quad \begin{bmatrix} x_n^2 & x_n & 1 \end{bmatrix} \begin{bmatrix} a_2 \\ a_1 \\ a_0 \end{bmatrix} = y_n \end{gathered} [xn2xn1]a2a1a0=yn
组合成矩阵形式为:
[ x 1 2 x 1 1 … … … x n 2 x n 1 ] [ a 2 a 1 a 0 ] = [ y 1 … y n ] \begin{gathered} \quad \begin{bmatrix} x_1^2 & x_1 & 1 \\ \ldots & \ldots & \ldots \\ x_n^2 & x_n & 1 \end{bmatrix} \begin{bmatrix} a_2 \\ a_1 \\ a_0 \end{bmatrix} = \begin{bmatrix} y_1\\ \ldots\\ y_n\end{bmatrix} \end{gathered} x12xn2x1xn11a2a1a0=y1yn
等号两边的矩阵左边同时乘以:
[ x 1 2 x 1 1 … … … x n 2 x n 1 ] T \begin{gathered} \quad \begin{bmatrix} x_1^2 & x_1 & 1 \\ \ldots & \ldots & \ldots \\ x_n^2 & x_n & 1 \end{bmatrix}^T \end{gathered} x12xn2x1xn11T
可得:
[ x 1 2 x 1 1 … … … x n 2 x n 1 ] T [ x 1 2 x 1 1 … … … x n 2 x n 1 ] [ a 2 a 1 a 0 ] = [ x 1 2 x 1 1 … … … x n 2 x n 1 ] T [ y 1 … y n ] \begin{gathered} \quad \begin{bmatrix} x_1^2 & x_1 & 1 \\ \ldots & \ldots & \ldots \\ x_n^2 & x_n & 1 \end{bmatrix}^T \begin{bmatrix} x_1^2 & x_1 & 1 \\ \ldots & \ldots & \ldots \\ x_n^2 & x_n & 1 \end{bmatrix} \begin{bmatrix} a_2 \\ a_1 \\ a_0 \end{bmatrix} = \begin{bmatrix} x_1^2 & x_1 & 1 \\ \ldots & \ldots & \ldots \\ x_n^2 & x_n & 1 \end{bmatrix}^T \begin{bmatrix} y_1\\ \ldots\\ y_n\end{bmatrix} \end{gathered} x12xn2x1xn11Tx12xn2x1xn11a2a1a0=x12xn2x1xn11Ty1yn
等号两边的矩阵左边同时乘以:
[ [ x 1 2 x 1 1 … … … x n 2 x n 1 ] T [ x 1 2 x 1 1 … … … x n 2 x n 1 ] ] − 1 \begin{gathered} \quad \begin{bmatrix} \begin{bmatrix} x_1^2 & x_1 & 1 \\ \ldots & \ldots & \ldots \\ x_n^2 & x_n & 1 \end{bmatrix}^T \begin{bmatrix} x_1^2 & x_1 & 1 \\ \ldots & \ldots & \ldots \\ x_n^2 & x_n & 1 \end{bmatrix} \end{bmatrix}^{-1} \end{gathered} x12xn2x1xn11Tx12xn2x1xn111
可得:
[ [ x 1 2 x 1 1 … … … x n 2 x n 1 ] T [ x 1 2 x 1 1 … … … x n 2 x n 1 ] ] − 1 [ x 1 2 x 1 1 … … … x n 2 x n 1 ] T [ x 1 2 x 1 1 … … … x n 2 x n 1 ] [ a 2 a 1 a 0 ] = [ [ x 1 2 x 1 1 … … … x n 2 x n 1 ] T [ x 1 2 x 1 1 … … … x n 2 x n 1 ] ] − 1 [ x 1 2 x 1 1 … … … x n 2 x n 1 ] T [ y 1 … y n ] \begin{gathered} \quad \begin{bmatrix} \begin{bmatrix} x_1^2 & x_1 & 1 \\ \ldots & \ldots & \ldots \\ x_n^2 & x_n & 1 \end{bmatrix}^T \begin{bmatrix} x_1^2 & x_1 & 1 \\ \ldots & \ldots & \ldots \\ x_n^2 & x_n & 1 \end{bmatrix} \end{bmatrix}^{-1} \begin{bmatrix} x_1^2 & x_1 & 1 \\ \ldots & \ldots & \ldots \\ x_n^2 & x_n & 1 \end{bmatrix}^T \begin{bmatrix} x_1^2 & x_1 & 1 \\ \ldots & \ldots & \ldots \\ x_n^2 & x_n & 1 \end{bmatrix} \begin{bmatrix} a_2 \\ a_1 \\ a_0 \end{bmatrix}= \begin{bmatrix} \begin{bmatrix} x_1^2 & x_1 & 1 \\ \ldots & \ldots & \ldots \\ x_n^2 & x_n & 1 \end{bmatrix}^T \begin{bmatrix} x_1^2 & x_1 & 1 \\ \ldots & \ldots & \ldots \\ x_n^2 & x_n & 1 \end{bmatrix} \end{bmatrix}^{-1} \begin{bmatrix} x_1^2 & x_1 & 1 \\ \ldots & \ldots & \ldots \\ x_n^2 & x_n & 1 \end{bmatrix}^T \begin{bmatrix} y_1 \\ \ldots \\ y_n \end{bmatrix} \end{gathered} x12xn2x1xn11Tx12xn2x1xn111x12xn2x1xn11Tx12xn2x1xn11a2a1a0=x12xn2x1xn11Tx12xn2x1xn111x12xn2x1xn11Ty1yn
则:
[ a 2 a 1 a 0 ] = [ [ x 1 2 x 1 1 … … … x n 2 x n 1 ] T [ x 1 2 x 1 1 … … … x n 2 x n 1 ] ] − 1 [ x 1 2 x 1 1 … … … x n 2 x n 1 ] T [ y 1 … y n ] \begin{gathered} \quad \begin{bmatrix} a_2 \\ a_1 \\ a_0 \end{bmatrix}= \begin{bmatrix} \begin{bmatrix} x_1^2 & x_1 & 1 \\ \ldots & \ldots & \ldots \\ x_n^2 & x_n & 1 \end{bmatrix}^T \begin{bmatrix} x_1^2 & x_1 & 1 \\ \ldots & \ldots & \ldots \\ x_n^2 & x_n & 1 \end{bmatrix} \end{bmatrix}^{-1} \begin{bmatrix} x_1^2 & x_1 & 1 \\ \ldots & \ldots & \ldots \\ x_n^2 & x_n & 1 \end{bmatrix}^T \begin{bmatrix} y_1 \\ \ldots \\ y_n \end{bmatrix} \end{gathered} a2a1a0=x12xn2x1xn11Tx12xn2x1xn111x12xn2x1xn11Ty1yn

C++程序为:

#include<iostream>
#include<math.h>

using namespace std;

double a[][2] = {
					 1, 4.00,
					 2, 6.40,
					 3, 8.00,
					 4, 8.80,
					 5, 9.22,
					 6, 9.50,
					 7, 9.70,
					 8, 9.86,
					 9, 10.00,
					10, 10.20,
					11, 10.32,
					12, 10.42,
					13, 10.50,
					14, 10.55,
					15, 10.58,
					16, 10.60 
				};

void matrix_inverse(double(*a)[3], double(*b)[3]); // 声明矩阵求逆函数

int main()
{
	double a0[N][3] = {0};
	double a1[3][N] = {0};
	double a2[3][3] = {0};
	double a3[3][3] = {0};
	double a4[3][N] = {0};
	double b0[N][1] = {0};
	double c0[3][1] = {0};

	for(int i = 0; i < N; ++i)
	{
		a0[i][0] = pow(a[i][0], 2);
		a0[i][1] = a[i][0];
		a0[i][2] = 1;
		
		a1[0][i] = pow(a[i][0], 2);		// 	矩阵转置 
		a1[1][i] = a[i][0];
		a1[2][i] = 1;
		
		b0[i][0] = a[i][1];
	}

	for(int i = 0; i < 3; ++i)		// 矩阵相乘 (k的取值来源于左边矩阵的列数或右边矩阵的行数) 
		for(int j = 0; j < 3; ++j)
			for(int k = 0; k < N; ++k)
				a2[i][j] += (a1[i][k] * a0[k][j]);

	matrix_inverse(a2, a3);		// 矩阵求逆 

	for(int i = 0; i < 3; ++i)
		for(int j = 0; j < N; ++j)
			for(int k = 0; k < 3; ++k)
				a4[i][j] += (a3[i][k] * a1[k][j]);
	
	for(int i = 0; i < 3; ++i)
		for(int j = 0; j < 1; ++j)
			for(int k = 0; k < N; ++k)
				c0[i][j] += (a4[i][k] * b0[k][j]);
	
//	for(int i = 0; i < 3; ++i)
//	{
//		for(int j = 0; j < 1; ++j)
//		{
//			cout << " " << c0[i][j] << "\t";
//		}
//		cout << "\n";
//	}
	return 0;
 }
 
 void matrix_inverse(double(*a)[3], double(*b)[3])			// 矩阵求逆 
{
	using namespace std;
	int i, j, k;
	double max, temp;
	// 定义一个临时矩阵t
	double t[3][3];
	// 将a矩阵临时存放在矩阵t[n][n]中
	for (i = 0; i < 3; i++)
		for (j = 0; j < 3; j++)
			t[i][j] = a[i][j];
	// 初始化B矩阵为单位矩阵
	for (i = 0; i < 3; i++)
		for (j = 0; j < 3; j++)
			b[i][j] = (i == j) ? (double)1 : 0;
	// 进行列主消元,找到每一列的主元
	for (i = 0; i < 3; i++)
	{
		max = t[i][i];
		// 用于记录每一列中的第几个元素为主元
		k = i;
		// 寻找每一列中的主元元素
		for (j = i + 1; j < 3; j++)
		{
			if (fabs(t[j][i]) > fabs(max))
			{
				max = t[j][i];
				k = j;
			}
		}
		//cout<<"the max number is "<<max<<endl;
		// 如果主元所在的行不是第i行,则进行行交换
		if (k != i)
		{
			// 进行行交换
			for (j = 0; j < 3; j++)
			{
				temp = t[i][j];
				t[i][j] = t[k][j];
				t[k][j] = temp;
				// 伴随矩阵B也要进行行交换
				temp = b[i][j];
				b[i][j] = b[k][j];
				b[k][j] = temp;
			}
		}
		if (t[i][i] == 0)
		{
			cout << "\nthe matrix does not exist inverse matrix\n";
			break;
		}
		// 获取列主元素
		temp = t[i][i];
		// 将主元所在的行进行单位化处理
		//cout<<"\nthe temp is "<<temp<<endl;
		for (j = 0; j < 3; j++)
		{
			t[i][j] = t[i][j] / temp;
			b[i][j] = b[i][j] / temp;
		}
		for (j = 0; j < 3; j++)
		{
			if (j != i)
			{
				temp = t[j][i];
				//消去该列的其他元素
				for (k = 0; k < 3; k++)
				{
					t[j][k] = t[j][k] - temp * t[i][k];
					b[j][k] = b[j][k] - temp * b[i][k];
				}
			}
		}
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值