数值计算—曲线拟合—最小二乘法(附源代码)

13 篇文章 3 订阅
12 篇文章 4 订阅

目录

最小二乘法的原理

实例:

求解结果:

c++程序源代码:


最小二乘法的原理

拟合函数:

                                                                        s(x)=\sum_{j=0}^{n}a_{j}\varphi _{j}(x)\quad \quad\quad \quad\quad \quad\quad \quad\quad \quad\quad \quad\quad \quad\quad \quad\quad \quad\quad\quad \left (1 \right )

式中:s(x)为拟合函数,  a_{j}为拟合系数,\varphi _{j}(x)为函数族

平方误差:

                                              \left \| \sigma \right \|_{2}^{2}=\sum_{i=0}^{m}(s(x_{i})-y_{i})^{2}=\sum_{i=0}^{m}(\sum_{j=0}^{m}a_{j}\varphi _{j}(x_{i})-y_{i})^{2}\quad \quad\quad \quad\quad \quad\quad \quad\quad \quad\quad \quad\quad \quad \left (2 \right )

(1)式可简化为线性方程组:

                                            \begin{pmatrix} (\varphi _{0},\varphi _{0}) & (\varphi _{0},\varphi _{1}) & \cdots &(\varphi _{0},\varphi _{n}) \\ (\varphi _{1},\varphi _{0})& (\varphi _{1},\varphi _{1}) & \cdots &(\varphi _{1},\varphi _{n}) \\ \vdots &\vdots & & \\ (\varphi _{n},\varphi _{0}) & (\varphi _{n},\varphi _{1}) & \cdots & (\varphi _{n},\varphi _{n}) \end{pmatrix}\begin{pmatrix} a_{0}\\ a_{1}\\ \vdots \\ a_{n} \end{pmatrix}=\begin{pmatrix} (\varphi _{0},f)\\ (\varphi _{1},f)\\ \vdots \\ (\varphi _{n},f) \end{pmatrix} \quad\quad \quad\quad\quad \quad\quad \quad\quad \quad \left (3 \right )

 式中:\varphi _{i}(x)为函数序列在点x_{i}上的法方程组。

多项式拟合函数S(x)的基函数为:

                                                         \varphi _{0}(x)=1,\varphi _{1}(x)=x,...,\varphi _{k}(x)=x^{k},,...,\varphi _{n}(x)=x^{n}\quad\quad \quad\quad \quad\quad \quad\quad \quad \left (4 \right )

基函数之间的内积为:

                                                                         (\varphi _{k},\varphi _{j})=\sum_{i=0}^{m}\varphi _{k}(x_{i})\varphi _{j}(x_{i})=\sum_{i=0}^{m}x_{i}^{k+j}\quad\quad\quad\quad \quad\quad \quad\quad \quad\quad \quad \left (5 \right )

                                                                           (\varphi _{k},f)=\sum_{i=0}^{m}\varphi _{k}(x_{i})y_{i}=\sum_{i=0}^{m}x_{i}^{k}y_{i}\quad\quad\quad\quad \quad\quad \quad\quad \quad\quad \quad\quad \quad \left (6 \right )

实例:

求解结果:

 

c++程序源代码:

//高等数值计算——曲线拟合——最小二乘法
//开发人员:chenshuai  开发日期:2019.11.20   邮箱:chenshuai0614@hrbeu.edu.cn 
#include "pch.h"
#include <iostream>
#include <fstream>//文件输入/输出流 
#include <iomanip> //参数化输入/输出 
#define n_polynomial 1  //需要拟合的多项式次数
#include <vector>
using namespace std;
vector<double> least_square_method(vector<double>x, vector<double>y, vector<double>a);//声明最小二乘法函数,x,y为原始数据,a为拟合多项式的系数列向量
double phi(double x, int n_cishu);  //函数族计算
vector<double> least_square_method(vector<double>x, vector<double>y, vector<double>a)//最小二乘法函数定义
{
	int n_data=size(x),n_num = size(a);
	vector<vector<double>>phi_phi;
	vector<double>phi_f;
	phi_f.resize(n_num);
	phi_phi.resize(n_num, vector<double>(n_num));
	for (int i = 0; i < n_num; i++)
	{
		for (int j = 0; j < n_num; j++)
		{
			for (int k = 0; k < n_data; k++)
			{
				phi_phi[i][j]= phi_phi[i][j]+phi(x[k],i)*phi(x[k], j);
			}
		}
		for (int k = 0; k < n_data; k++)
		{
			phi_f[i] = phi_f[i] + phi(x[k], i)*y[k];
		}
	}
	a = gaussian_elimination(phi_phi, phi_f);//多项式系数求解采用高斯消去法“参考我以前写的文章(含代码)”https://blog.csdn.net/weixin_41788456/article/details/102485139
	//平方误差求解
	double delta_2=0;
	for (int i = 0; i < n_data; i++)
	{
		delta_2 = delta_2 +y[i]*y[i];
	}
	for (int i = 0; i < n_num; i++)
	{
		delta_2 = delta_2 - a[i] * phi_f[i];
	}
	//系数矩阵与平方误差输出
	for (int i = 0; i < n_num; i++)
	{
		for (int j = 0; j < n_num; j++)
		{
			cout << fixed << setprecision(2) << setw(12) << phi_phi[i][j];
		}
		cout << fixed << setprecision(4) << setw(12) << phi_f[i] << endl;
	}
	cout << fixed << setprecision(4) << setw(12) << delta_2 << endl;
	return a;
}
double phi(double x, int n_cishu)  //函数族计算
{
	double y;
	y = pow(x, n_cishu);
	return y;
}
int main()
{
	vector<double>x_i= { 1.9,2,2.1,2.5,2.7,2.7,3.5,3.5,4,4,4.5,4.6,5,5.2,6,6.3,6.5,7.1,8,8,8.9,9,9.5,10};//原始数据
	vector<double>y_i= { 1.4,1.3,1.8,2.5,2.8,2.5,3,2.7,4,3.5,4.2,3.5,5.5,5,5.5,6.4,6,5.3,6.5,7,8.5,8,8.1,8.1 };
	vector<double>a(n_polynomial + 1);
	int n_data = size(x_i);
	a=least_square_method(x_i, y_i, a);//最小二乘法拟合函数调用
	cout << "多项式系数解为:" << endl;
	for (int i = 0; i < n_polynomial + 1; i++)
		cout << "a[" << i << "]=" << fixed << setprecision(2) << setw(5) << a[i] << endl;
	ofstream out("一次函数拟合函数数据.dat");
	double x,y, precision=0.01;
	for (x = x_i[0]; x <= x_i.back(); x = x + precision)
	{
		y = 0.0;
		for (int i = 0; i < n_polynomial + 1; i++)
		{
			y = y + a[i] * pow(x, i);
		}
		out << fixed << setprecision(4) << setw(12) << x << fixed << setprecision(4) << setw(12) << y << endl;
	}
	out.close();
	ofstream out1("原始数据.dat");
	for (int i = 0; i < n_data; i++)
	{
		out1 << fixed << setprecision(4) << setw(12) << x_i[i] << fixed << setprecision(4) << setw(12) << y_i[i] << endl;
	}
	out1.close();	
}

 

  • 3
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值