C++最小二乘拟合 (高阶最小二乘拟合)

文章目录

原文链接:
https://blog.csdn.net/weixin_44344462/article/details/88850409

https://blog.csdn.net/xsz591541060/article/details/107532611

配置Eigen矩阵运算库
后续计算需要利用矩阵运算来求解拟合系数,用到Eigen矩阵运算库,配置方法可自行搜索或MacOs可以参考Mac配置Eigen库进行配置。

拟合原理
以二次曲线拟合为例,拟合曲线应满足以下方程:
在这里插入图片描述
即有:
在这里插入图片描述
由上面最后一个等式利用矩阵的转置与求逆,则可以得出其拟合曲线的系数W矩阵。

C++最小二乘拟合代码
以下代码理论上可以完成N阶的曲线拟合,需要对参数N进行设置,并提供正确的数据点。

#include <Eigen/Core>
#include <Eigen/Dense>
#include <Eigen/Geometry>
#include <Eigen/Eigenvalues>
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <cmath>

using namespace std;


int main() {
    // txt点数据文件路径
    const string fileName = "./points.txt";
    
    // 设置是几次拟合
    const int N = 2;
    
    // 创建两个vector
    vector<float> x, y;
    
    // 读取文件
    ifstream f(fileName);
    
    if (!f) {
        cout << "数据文件打开失败" << endl;
        exit(EXIT_FAILURE);
    }
    
    float tempx, tempy;
    
    while (f >> tempx >> tempy) {
        x.push_back(tempx);
        y.push_back(tempy);
    }
    
    if (x.size() != y.size()) {
        cout << "数据文件内容有误" << endl;
        exit(EXIT_FAILURE);
    }
    
    // 创建A矩阵
    Eigen::MatrixXd A(x.size(), N + 1);
    
    for (unsigned int i = 0; i < x.size(); ++i) {  // 遍历所有点
        
        for (int n = N, dex = 0; n >= 1; --n, ++dex) {  // 遍历N到1阶
            A(i, dex) = pow(x[i], n);
        }
        
        A(i, N) = 1;  //
    }
    
    // 创建B矩阵
    Eigen::MatrixXd B(y.size(), 1);
    
    for (unsigned int i = 0; i < y.size(); ++i) {
        B(i, 0) = y[i];
    }
  	
    // 创建矩阵W
    Eigen::MatrixXd W;
    W = (A.transpose() * A).inverse() * A.transpose() * B;
    
  	// 打印W结果
    cout << W << endl;
}

与设置的系数相吻合,但这是建立在噪声为0的情况下的结果。

#include <QCoreApplication>
#include <QtCore>
#include <QObject>
#include <QVector>
#include <Eigen/Core>
#include <Eigen/Dense>
#include <Eigen/Geometry>
#include <Eigen/Eigenvalues>
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <cmath>

using namespace Eigen;
using namespace std;


bool polyfit(const QVector<double> &x, const QVector<double> &y, quint8 dim, QVector<double> &z)
{
    Q_ASSERT(x.size() == y.size());
    quint8 N = 3;
    // 设置是几次拟合
    if(dim < 0 && dim > 20)
    {
        return false;
    }
    N = dim;
        // 创建A矩阵
        Eigen::MatrixXd A(x.size(), N + 1);

        for (unsigned int i = 0; i < x.size(); ++i) {  // 遍历所有点

            for (int n = N, dex = 0; n >= 1; --n, ++dex) {  // 遍历N到1阶
                A(i, dex) = pow(x[i], n);
            }

            A(i, N) = 1;  //
        }

        // 创建B矩阵
        Eigen::MatrixXd B(y.size(), 1);

        for (unsigned int i = 0; i < y.size(); ++i) {
            B(i, 0) = y[i];
        }

        // 创建矩阵W
        Eigen::MatrixXd W;
        W = (A.transpose() * A).inverse() * A.transpose() * B;



        // 打印W结果
        cout << W << endl;

        cout << "rows:"<<W.rows() << " cols:" << W.cols() << endl;

        double t;
        z.clear();
        for(int i = 0; i< W.rows()*W.cols(); i++)
        {
            t = W(i,0);
            z.push_back(t);
        }

    return true;
}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    // 创建两个vector
    QVector<double> x, y, z;
    x.push_back(1);
    x.push_back(2);
    x.push_back(3);
    x.push_back(4);
    x.push_back(5);
    x.push_back(6);

    y.push_back(10);
    y.push_back(13);
    y.push_back(15);
    y.push_back(21);
    y.push_back(22);
    y.push_back(28);

    bool ret = polyfit(x, y, 5, z);

    qDebug()<<"QVector z: "<<z;


    return a.exec();
}

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值