Polynomial Fitting Principle and Code Implementation of Least Squares Method

Polynomial fitting of the least squares method
Given a series of points, use the least squares method to fit the polynomial curve function of these points. Assume that the fitted polynomial (k term) function is:
insert image description here
and assume that the real curve function is:
insert image description here
then for a given n points (xi, yi), 0<i≤n, the deviation between the fitted curve and the actual should be the smallest, that is :
insert image description here
Then the problem is transformed into: find a set of solutions (a0,a1,a2,...,ak)^T, so that the value of the function L is the smallest . It can be seen from the extreme value conditions that when L takes the minimum value of a set of solutions, the partial derivative of L to it is 0; in order to solve the problem, the partial derivative of ai is calculated for L and set to 0: Simplification can be obtained: expressed as
insert image description here
a
insert image description here
matrix For:
insert image description here
Obviously the above formula is a problem of solving linear equations: A*X=B.

When programming, it is not necessary to calculate (k+1)^2 times for the acquisition of A, and it can be found that there are only 2k+1 elements in A: so when programming, you only need to calculate ∑_(i=1)n▒x_i0 ,∑_(i=1)n▒x_i1 ,…,∑_(i=1)n▒x_i(k+1) ,…,∑_(i=1)n ▒x_i(k+k)
the 2k+1 items first, and then calculate them according to the law Just fill in A. The following sample code demonstrates solving the A*X=B problem using the Qr decomposition algorithm of the Eigen library.

#include <Eigen/Dense> 
//--Input
//---x:数据点的x坐标值数组
//---y:数据点的y坐标值数组
//---n:数据点的个数
//---k:多项式的阶
//--Output
//---返回A*X=B中的解X
Eigen::VectorXd polynomialFitting(double*x, double*y, unsigned n, unsigned k)
{
    
    
    Eigen::MatrixXd A=Eigen::MatrixXd::Zero(k+1,k+1);
    Eigen::VectorXd B=Eigen::VectorXd::Zero(k+1);

    double*x_pow_sum=new double[2*k+1];//存放A中2k+1项不重复元素
    for(unsigned i=0;i<2*k+1;i++)
    {
    
    
        double sum=0.;
        for(unsigned j=0;j<n;j++)
        {
    
    
            sum+=pow(x[j],i);//计算每项幂的和
        }
        x_pow_sum[i]=sum;//
    }
    for(unsigned i=0;i<k+1;i++)
    {
    
    
        for(unsigned j=0;j<k+1;j++)
        {
    
    
            A(i,j)=x_pow_sum[i+j];//按规律将2k+1项不重复元素填入矩阵A
        }
    }
    for(unsigned i=0;i<k+1;i++)
    {
    
    
        double sum=0;
        for(unsigned j=0;j<n;j++)
        {
    
    
            sum=sum+pow(x[j],i)*y[j];//计算B的每个元素
        }
        B[i]=sum;
    }
    //利用Eigen库中的Qr分解求解X
    Eigen::VectorXd X=A.colPivHouseholderQr().solve(B);
    return X;
}

If the Eigen library is not installed, you can use the Gaussian elimination method or the selected pivot method to write the solution code.

Guess you like

Origin blog.csdn.net/qq_38222947/article/details/118212408