LM算法详解
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算法详解的更多相关文章
- BM算法 Boyer-Moore高质量实现代码详解与算法详解
Boyer-Moore高质量实现代码详解与算法详解 鉴于我见到对算法本身分析非常透彻的文章以及实现的非常精巧的文章,所以就转载了,本文的贡献在于将两者结合起来,方便大家了解代码实现! 算法详解转自:h ...
- kmp算法详解
转自:http://blog.csdn.net/ddupd/article/details/19899263 KMP算法详解 KMP算法简介: KMP算法是一种高效的字符串匹配算法,关于字符串匹配最简 ...
- 机器学习经典算法详解及Python实现--基于SMO的SVM分类器
原文:http://blog.csdn.net/suipingsp/article/details/41645779 支持向量机基本上是最好的有监督学习算法,因其英文名为support vector ...
- [转] KMP算法详解
转载自:http://www.matrix67.com/blog/archives/115 KMP算法详解 如果机房马上要关门了,或者你急着要和MM约会,请直接跳到第六个自然段. 我们这里说的K ...
- 【转】AC算法详解
原文转自:http://blog.csdn.net/joylnwang/article/details/6793192 AC算法是Alfred V.Aho(<编译原理>(龙书)的作者),和 ...
- KMP算法详解(转自中学生OI写的。。ORZ!)
KMP算法详解 如果机房马上要关门了,或者你急着要和MM约会,请直接跳到第六个自然段. 我们这里说的KMP不是拿来放电影的(虽然我很喜欢这个软件),而是一种算法.KMP算法是拿来处理字符串匹配的.换句 ...
- EM算法详解
EM算法详解 1 极大似然估计 假设有如图1的X所示的抽取的n个学生某门课程的成绩,又知学生的成绩符合高斯分布f(x|μ,σ2),求学生的成绩最符合哪种高斯分布,即μ和σ2最优值是什么? 图1 学生成 ...
- Tarjan算法详解
Tarjan算法详解 今天偶然发现了这个算法,看了好久,终于明白了一些表层的知识....在这里和大家分享一下... Tarjan算法是一个求解极大强联通子图的算法,相信这些东西大家都在网络上百度过了, ...
- 安全体系(二)——RSA算法详解
本文主要讲述RSA算法使用的基本数学知识.秘钥的计算过程以及加密和解密的过程. 安全体系(零)—— 加解密算法.消息摘要.消息认证技术.数字签名与公钥证书 安全体系(一)—— DES算法详解 1.概述 ...
- 安全体系(三)——SHA1算法详解
本文主要讲述使用SHA1算法计算信息摘要的过程. 安全体系(零)—— 加解密算法.消息摘要.消息认证技术.数字签名与公钥证书 安全体系(一)—— DES算法详解 安全体系(二)——RSA算法详解 为保 ...
随机推荐
- PHP 正在“杀死”Python
最近,我突然发现自己好像又在逆潮流而动.可能我的想法与很多朋友不同,我认为 PHP 这个编程语言界的"混蛋"比以往任何时候都更受欢迎. 或许你会质疑--PHP 不是已经完蛋了吗?市 ...
- .NET跨平台框架选择之一 - Avalonia UI
本文阅读目录 1. Avalonia UI简介 Avalonia UI文档教程:https://docs.avaloniaui.net/docs/getting-started 随着跨平台越来越流行, ...
- 禁用显卡自动更新(解决官办驱动和OEM驱动相冲)
起因 有一天打开MC(我的世界)时候突然显示显卡不支持,想了想可能是自己捣鼓电脑的时候弄坏了,提示说版本不支持,一看自己的驱动还是上古版本,但是之前都是可以正常玩的,想着更新下驱动就行了呗,更新完&q ...
- i春秋broken
点开一个附带超链接的网页,直接点击file跳转到broken网页 网页里面是一个jsfuck代码 Jsfuck代码的执行方法 ①复制 ②打开firefox浏览器 ③按下F12 ④选择上方的控制台 ⑤在 ...
- CodeGeeX:vscode中全新的智能代码补全插件
大家好我是费老师,代码智能补全是近几年非常热门的话题,有前不久宣告项目终结的kite,反响平平的tabnine,以及最近吃了一堆官司的copilot. 而广大从事编程工作的用户只关心市面上的代码智能补 ...
- JavaEE Day01 基础加强
今日内容 1.Junit单元测试(测试类) 2.反射 3.注解 一.Junit单元测试 1.概述 测试分类 1. 黑盒测试:不需要写代码,给输入值,看程序是否能够输出期望的值 2.白盒测试:需要写代码 ...
- JavaEE课程复习1--数据库相关操作
〇.本模块内容简介 30=(DB5+前端5+Web Core15+Project5) Junit.注解 MySQL.JDBC.JDBCUtils.c3p0.Druid连接池及工具类.JDBCTempl ...
- ORM数据库查询优化only与defer(select_related与prefetch_related)
目录 一:数据库查询优化 1.ORM语句特点 2.only 3.defer 4.only与defer区别 5.select_related与prefetch_related 6.select_rela ...
- week_9(异常检测)
Andrew Ng 机器学习笔记 ---By Orangestar Week_9 This week, we will be covering anomaly detection which is w ...
- python进阶之路7 数据类型的内置方法
内容回顾 while 循环补充说明 1.死循环 2.while循环嵌套和全局标志位 for循环 1.for 变量名 in 待遍历数据 for循环体代码 2.for 也可以与break continue ...