LM算法参数优化实例——残差函数、雅可比矩阵

【目标】:使用LM算法估计 y = e x p ( a t 2 + b t + c ) y=exp(at^2+bt+c) y=exp(at2+bt+c)参数a, b, c
已知量: t t t及与之对应的含有噪声的量测值 y ^ \hat{y} y^;同时,模型已知(仅未知参数)。

仿真数据生成

取参数为a=1.0, b=2.0, c=1.0

	double a=1.0, b=2.0, c=1.0;         // 真实参数值
    int N = 100;                        // 数据点数目
    double w_sigma= 1.;                 // 噪声Sigma值(方差)

    std::default_random_engine generator;
    std::normal_distribution<double> noise(0.,w_sigma);

	// 构造 N 次观测
    for (int i = 0; i < N; ++i) {
        double t = i/100.;             // t的取值在0.0~1.0之间
        double n = noise(generator);
        double y = std::exp( a*t*t + b*t + c ) + n; //  // 含噪声的观测 y
    }

确定待优化变量、残差函数、及损失函数

待优化变量(Vertex): 参数a, b, c,此时放在一个 3 × 1 3\times 1 3×1的向量 x x x中;
残差函数(Edge): 以第k步迭代参数的估计值 x k x_k xk(参数)和第i个自变量代入已知模型得到的预测值 y ^ k \hat{y}_k y^k,和第k步迭代的含有噪声的量测值 y k y_k yk的差值作为残差。记为 f i ( x k ) f_i(x_k) fi(xk)
损失函数(Problem): F ( x k ) = Σ i = 1 N ∥ f i ( x k ) ∥ 2 F(x_k)=\Sigma_{i=1}^N\|f_i(x_k)\|_2 F(xk)=Σi=1Nfi(xk)2

【代码1-待优化变量】:

    shared_ptr< CurveFittingVertex > vertex(new CurveFittingVertex());
    vertex->SetParameters(Eigen::Vector3d (0.,0.,0.));

其中,CurveFittingVertex继承自Vertex,且在构造函数中指明了一个3维向量:

// 曲线模型的顶点,模板参数:优化变量维度
class CurveFittingVertex: public Vertex{
public:
    CurveFittingVertex(): Vertex(3) {}  // abc: 三个参数, Vertex 是 3 维的
};

Vertex在构造函数中,其成员变量VecX Parameters_;resize为一个3维向量:

explicit Vertex(int num_dimension, int local_dimension = -1);//类内的声明
Vertex::Vertex(int num_dimension, int local_dimension) {    // 类外的定义
    parameters_.resize(num_dimension, 1);
    id_ = global_vertex_id++; // 初始值有:unsigned long global_vertex_id = 0;
}

注:VecX实际上是一个别名typedef Eigen::Matrix<double, Eigen::Dynamic, 1> VecX;

【代码2-残差项】
对于每一个观测量,构造其对应的残差(此时还并未真正去计算):

// 每个观测对应的残差函数
shared_ptr< CurveFittingEdge > edge(new CurveFittingEdge(t,y));

// CurveFittingEdge 构造函数为:
class CurveFittingEdge: public Edge{
public:
    CurveFittingEdge( double x, double y ): Edge(1,1, std::vector<std::string>{"abc"}) {
        x_ = x;
        y_ = y;
    }
    ...
}

父类Edge的构造函数为:

Edge::Edge(int residual_dimension, int num_verticies,
           const std::vector<std::string> &verticies_types) {
    residual_.resize(residual_dimension, 1); // 残差向量
    jacobians_.resize(num_verticies);        // 雅可比矩阵
    // 信息矩阵
    Eigen::MatrixXd information(residual_dimension, residual_dimension);
    information.setIdentity();
    information_ = information;
}
...
补充其中用到的几个类型
    VecX residual_;                 // 残差
    std::vector<MatXX> jacobians_;  // 雅可比,每个雅可比维度是 residual x vertex[i]
    MatXX information_;             // 信息矩阵
    VecX observation_;              // 观测信息

同时,对于该观测量及其对应的残差,指定它们与哪些待优化的变量(参数)有关!

std::vector<std::shared_ptr<Vertex>> edge_vertex;
edge_vertex.push_back(vertex);  //本次曲线拟合例题中仅一个顶点(其他或许多个)
edge->SetVertex(edge_vertex);  // 指定该edge对应的顶点

// 该成员函数的定义:
bool SetVertex(const std::vector<std::shared_ptr<Vertex>> &vertices) {
    verticies_ = vertices;
    return true;
}
// 其中,成员变量的定义:
std::
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值