求解非线性最小二乘法 Eigen

5 篇文章 0 订阅
// 利用Eigen 求解非线性最小二乘;
// 示例:<span style="font-family: Arial, Helvetica, sans-serif;">y = 10*(x0+3)^2 + (x1-5)^2</span><pre name="code" class="html"><span style="font-family: Arial, Helvetica, sans-serif;">#include "math.h"</span>
 
#include "iostream"
#include "vector"
#include "list"

using namespace std;

#include "Eigen/Dense"
#include "Eigen/Core"
#include <unsupported/Eigen/NonLinearOptimization>
#include <unsupported/Eigen/NumericalDiff>

using namespace Eigen;


// Generic functor
template<typename _Scalar, int NX = Eigen::Dynamic, int NY = Eigen::Dynamic>
struct Functor
{
	typedef _Scalar Scalar;
	enum {
		InputsAtCompileTime = NX,
		ValuesAtCompileTime = NY
	};
	typedef Eigen::Matrix<Scalar,InputsAtCompileTime,1> InputType;
	typedef Eigen::Matrix<Scalar,ValuesAtCompileTime,1> ValueType;
	typedef Eigen::Matrix<Scalar,ValuesAtCompileTime,InputsAtCompileTime> JacobianType;

	int m_inputs, m_values;

	Functor() : m_inputs(InputsAtCompileTime), m_values(ValuesAtCompileTime) {}
	Functor(int inputs, int values) : m_inputs(inputs), m_values(values) {}

	int inputs() const { return m_inputs; }
	int values() const { return m_values; }

};


struct my_functor : Functor<double>
{
	// 输出个数必须大于输入个数, 故用2不用1;
	my_functor(void): Functor<double>(2, 2) {}
	int operator()(const Eigen::VectorXd &x, Eigen::VectorXd &fvec) const
	{
		// Implement y = 10*(x0+3)^2 + (x1-5)^2
		fvec(0) = 10.0*pow(x(0)+3.0,2) +  pow(x(1)-5.0,2);
		fvec(1) = 0;

		return 0;
	}
};

int main(int argc, char *argv[])
{
	Eigen::VectorXd x(2);
	x(0) = 1.0;
	x(1) = 3.0;

	my_functor functor;
	Eigen::NumericalDiff<my_functor> numDiff(functor);
	Eigen::LevenbergMarquardt<Eigen::NumericalDiff<my_functor>,double> lm(numDiff);

	Eigen::VectorXd y(2);
	functor.operator()(x, y);

	std::cout << "x first input: \n" << x << std::endl;
	std::cout<<"y first outpout: \n" << y << std::endl;

	lm.parameters.maxfev = 1000;
	lm.parameters.xtol = 1.0e-8;

	int iRet = lm.minimize(x);
	std::cout << "迭代次数:\n"<<lm.iter << std::endl;
	std::cout << "计算标志:\n" << iRet << std::endl;

	std::cout << "x finnal: \n" << x << std::endl;

	functor.operator()(x, y);
	std::cout<<"y outpout((minimized): \n" << y << std::endl;

	return 0;
}

// 最终看到输出了x = [-3.0, 5.0]. 使得目标最小!


  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Qt是一个跨平台的C++应用程序开发框架,它提供了丰富的功能和工具来帮助开发人员构建各种类型的应用程序。虽然Qt本身并没有直接提供最小二乘法线性拟合的功能,但你可以使用Qt来实现该功能。下面是一个简单的介绍: 1. 导入必要的:在Qt项目中,你需要导入一些数学,如Eigen、GSL等,以便进行数值计算和优化。 2. 定义模型函数:首先,你需要定义一个适当的线性模型函数来描述你的数据。例如,如果你的数据可以用一个二次多项式来拟合,那么你可以定义一个函数来计算二次多项式的值。 3. 定义误差函数:接下来,你需要定义一个误差函数来衡量模型预测值与实际观测值之间的差异。最小二乘法的目标是最小化这个误差函数。 4. 优化参数:使用最小二乘法进行线性拟合时,你需要选择一个优化算法来找到使误差函数最小化的参数。常见的优化算法有Levenberg-Marquardt算法和Gauss-Newton算法。 5. 实施拟合:根据选定的优化算法,使用数值计算中提供的相关函数来实施拟合过程。这些函数通常需要提供初始参数值和观测数据。 总结起来,Qt本身并不直接提供最小二乘法线性拟合的功能,但你可以使用Qt作为开发框架来实现该功能。你可以借助第三方数学来进行数值计算和优化,定义模型函数和误差函数,并使用相应的优化算法进行拟合。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值