1. 高斯牛顿法

残差函数f(x)为非线性函数,对其一阶泰勒近似有:



这里的J是残差函数f的雅可比矩阵,带入损失函数的:



令其一阶导等于0,得:



这就是论文里常看到的normal equation。

2.LM

LM是对高斯牛顿法进行了改进,在求解过程中引入了阻尼因子:

2.1 阻尼因子的作用:

2.2 阻尼因子的初始值选取:

一个简单的策略就是:

2.3 阻尼因子的更新策略





3.核心代码讲解

3.1 构建H矩阵

void Problem::MakeHessian() {
TicToc t_h;
// 直接构造大的 H 矩阵
ulong size = ordering_generic_;
MatXX H(MatXX::Zero(size, size));
VecX b(VecX::Zero(size)); // TODO:: accelate, accelate, accelate
//#ifdef USE_OPENMP
//#pragma omp parallel for
//#endif // 遍历每个残差,并计算他们的雅克比,得到最后的 H = J^T * J
for (auto &edge: edges_) { edge.second->ComputeResidual();
edge.second->ComputeJacobians(); auto jacobians = edge.second->Jacobians();
auto verticies = edge.second->Verticies();
assert(jacobians.size() == verticies.size());
for (size_t i = 0; i < verticies.size(); ++i) {
auto v_i = verticies[i];
if (v_i->IsFixed()) continue; // Hessian 里不需要添加它的信息,也就是它的雅克比为 0 auto jacobian_i = jacobians[i];
ulong index_i = v_i->OrderingId();
ulong dim_i = v_i->LocalDimension(); MatXX JtW = jacobian_i.transpose() * edge.second->Information();
for (size_t j = i; j < verticies.size(); ++j) {
auto v_j = verticies[j]; if (v_j->IsFixed()) continue; auto jacobian_j = jacobians[j];
ulong index_j = v_j->OrderingId();
ulong dim_j = v_j->LocalDimension(); assert(v_j->OrderingId() != -1);
MatXX hessian = JtW * jacobian_j;
// 所有的信息矩阵叠加起来
H.block(index_i, index_j, dim_i, dim_j).noalias() += hessian;
if (j != i) {
// 对称的下三角
H.block(index_j, index_i, dim_j, dim_i).noalias() += hessian.transpose();
}
}
b.segment(index_i, dim_i).noalias() -= JtW * edge.second->Residual();
} }
Hessian_ = H;
b_ = b;
t_hessian_cost_ += t_h.toc(); delta_x_ = VecX::Zero(size); // initial delta_x = 0_n; }

3.2 将构建好的H矩阵加上阻尼因子

void Problem::AddLambdatoHessianLM() {
ulong size = Hessian_.cols();
assert(Hessian_.rows() == Hessian_.cols() && "Hessian is not square");
for (ulong i = 0; i < size; ++i) {
Hessian_(i, i) += currentLambda_;
}
}

3.3 进行求解后,验证该步的解是否合适,代码对应阻尼因子的更新策略

bool Problem::IsGoodStepInLM() {
double scale = 0;
scale = delta_x_.transpose() * (currentLambda_ * delta_x_ + b_);
scale += 1e-3; // make sure it's non-zero :) // recompute residuals after update state
// 统计所有的残差
double tempChi = 0.0;
for (auto edge: edges_) {
edge.second->ComputeResidual();
tempChi += edge.second->Chi2();
} double rho = (currentChi_ - tempChi) / scale;
if (rho > 0 && isfinite(tempChi)) // last step was good, 误差在下降
{
double alpha = 1. - pow((2 * rho - 1), 3);
alpha = std::min(alpha, 2. / 3.);
double scaleFactor = (std::max)(1. / 3., alpha);
currentLambda_ *= scaleFactor;
ni_ = 2;
currentChi_ = tempChi;
return true;
} else {
currentLambda_ *= ni_;
ni_ *= 2;
return false;
}
}

LM算法详解的更多相关文章

  1. BM算法  Boyer-Moore高质量实现代码详解与算法详解

    Boyer-Moore高质量实现代码详解与算法详解 鉴于我见到对算法本身分析非常透彻的文章以及实现的非常精巧的文章,所以就转载了,本文的贡献在于将两者结合起来,方便大家了解代码实现! 算法详解转自:h ...

  2. kmp算法详解

    转自:http://blog.csdn.net/ddupd/article/details/19899263 KMP算法详解 KMP算法简介: KMP算法是一种高效的字符串匹配算法,关于字符串匹配最简 ...

  3. 机器学习经典算法详解及Python实现--基于SMO的SVM分类器

    原文:http://blog.csdn.net/suipingsp/article/details/41645779 支持向量机基本上是最好的有监督学习算法,因其英文名为support vector  ...

  4. [转] KMP算法详解

    转载自:http://www.matrix67.com/blog/archives/115 KMP算法详解 如果机房马上要关门了,或者你急着要和MM约会,请直接跳到第六个自然段.    我们这里说的K ...

  5. 【转】AC算法详解

    原文转自:http://blog.csdn.net/joylnwang/article/details/6793192 AC算法是Alfred V.Aho(<编译原理>(龙书)的作者),和 ...

  6. KMP算法详解(转自中学生OI写的。。ORZ!)

    KMP算法详解 如果机房马上要关门了,或者你急着要和MM约会,请直接跳到第六个自然段. 我们这里说的KMP不是拿来放电影的(虽然我很喜欢这个软件),而是一种算法.KMP算法是拿来处理字符串匹配的.换句 ...

  7. EM算法详解

    EM算法详解 1 极大似然估计 假设有如图1的X所示的抽取的n个学生某门课程的成绩,又知学生的成绩符合高斯分布f(x|μ,σ2),求学生的成绩最符合哪种高斯分布,即μ和σ2最优值是什么? 图1 学生成 ...

  8. Tarjan算法详解

    Tarjan算法详解 今天偶然发现了这个算法,看了好久,终于明白了一些表层的知识....在这里和大家分享一下... Tarjan算法是一个求解极大强联通子图的算法,相信这些东西大家都在网络上百度过了, ...

  9. 安全体系(二)——RSA算法详解

    本文主要讲述RSA算法使用的基本数学知识.秘钥的计算过程以及加密和解密的过程. 安全体系(零)—— 加解密算法.消息摘要.消息认证技术.数字签名与公钥证书 安全体系(一)—— DES算法详解 1.概述 ...

  10. 安全体系(三)——SHA1算法详解

    本文主要讲述使用SHA1算法计算信息摘要的过程. 安全体系(零)—— 加解密算法.消息摘要.消息认证技术.数字签名与公钥证书 安全体系(一)—— DES算法详解 安全体系(二)——RSA算法详解 为保 ...

随机推荐

  1. 自动增加 Android App 的版本号

    一般的 C# 应用程序中都有一个 AssemblyInfo.cs 文件,其中的 AssemblyVersion attribute 就可以用来设置该应用程序的版本号.譬如, [assembly: As ...

  2. Day30.1:Math的常用方法

    Math 1.1 Math概述 Math类在Java.lang包下,不需要导包 public final class Math extends Object Math含有基本的数字运算方法,没有构造器 ...

  3. Java基础知识篇【gitee】

    https://snailclimb.gitee.io/javaguide 一.Java基本功 Java一次编译,字节码通过JVM,处处运行jsp会转化为servlet,也要由jdk编译OracleJ ...

  4. 【实习项目介绍】XXXXX大数据平台介绍

    一.技术架构 1.整体介绍及架构 (1)概述 Odeon大数据平台以全图形化Web操作的形式为用户提供一站式的大数据能力:包括数据采集.任务编排.调度及处理.数据展现(BI)等:同时提供完善的权限管理 ...

  5. 有来实验室|第一篇:Seata1.5.2版本部署和开源全栈商城订单支付业务实战

    在线体验:Seata实验室 一. 前言 相信 youlai-mall 的实验室大家有曾在项目中见到过,但应该都还处于陌生的阶段,毕竟在此之前实验室多是以概念般的形式存在,所以我想借着此次的机会,对其进 ...

  6. jQuery类库

    jQuery介绍 1. jQuery是一个轻量级的.兼容多浏览器的JavaScript库. 2. jQuery使用户能够更方便地处理HTML Document.Events.实现动画效果.方便地进行A ...

  7. OpenJudge 1.8.11 图像旋转

    11:图像旋转 总时间限制: 1000ms 内存限制: 65536kB 描述 输入一个n行m列的黑白图像,将它顺时针旋转90度后输出. 输入 第一行包含两个整数n和m,表示图像包含像素点的行数和列数. ...

  8. 总结开源项目中的常见坏实践(Bad Practice)

    一些开源项目包含了各种编程的最佳实践供人参考学习和借鉴.但是也有一些开源项目虽然初衷是好的.但是包含了一些代码的坏实践.特别是对于一部分刚入行的大学生来说,可能会给到一些错误的示范.于是在此列举一些项 ...

  9. 【转载】github.com访问慢解决办法

    打开网站 IPAddress.com ,找到页面中下方的"IP Address Tools – Quick Links" 分别输入github.global.ssl.fastly. ...

  10. 旧酒换新瓶,新版M1/M2芯片Macos(Ventura)安装古早版本Python2.7(Python2.x)

    向下兼容特性是软件开发系统的一个重要指标,它是指一个新的系统或者软件能够与旧的系统或软件兼容并正常运行.这意味着旧系统或软件可以在新系统或软件中使用,而不会出现问题.向下兼容对于提高软件或系统的可用性 ...