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算法详解 为保 ...
随机推荐
- Azure DevOps Server 用户组加入 Azure AD Domain Service 管理用户
一,引言 今天我们继续讲解 Azure DevOps Server 的内容,对于管理用户组除了在 Azure DevOps Server 服务器上添加管理员方式外,还有没有其他方式,Azure Dev ...
- GeoServer 2.15.0 开启跨域设置
GeoServe老版本可能开启跨域设置比较麻烦,但2.15.0版本还是比较简单的. 首先找到安装目录下的 webapps\geoserver\WEB-INF\web.xml 文件,打开进行编辑,建议编 ...
- Tkinter根据屏幕分辨率最大化适应屏幕
还不能够实现所有组件随分辨率自动变化 # 实现的是界面覆盖整个屏幕 from tkinter import * import win32api, win32con # 获取屏幕的分辨率 width = ...
- 【Shell脚本案例】案例3:批量创建100个用户并设置密码
一.背景 新入职员工创建用户 二.常规操作 useradd zhangsan ls /home/ password zhangsan 三.考虑问题 1.实现自动输入密码,将其存到文件中 passwor ...
- base64解析爬取糗百
一.缘由 这是我之前刚开始学习的时候爬取糗百的练习内容,主要练习的是bs64解析.虽然现在用的不是特别的多,但是当初的时候用起来还是非常的顺手的. 二.代码实现 #coding:utf-8 impor ...
- 【数据结构与算法】希尔排序 python和c++实现
算法思路 每一次:固定间隔把数据分组,每一组进行排序 每次比上次选取更小的间隔分组,再每组排序,直到间隔为1 代码 c++:(越看越不明白了,后看) int gap = length;//length ...
- .NET周报【12月第2期 2022-12-15】
国内文章 九哥聊Kestrel网络编程第一章:开发一个Redis服务器 https://mp.weixin.qq.com/s/HJYnBE-7wbvkAYHxQaq3eQ 我和拥有多个.NET 千星开 ...
- 8000字详解Thread Pool Executor
摘要:Java是如何实现和管理线程池的? 本文分享自华为云社区<JUC线程池: ThreadPoolExecutor详解>,作者:龙哥手记 . 带着大厂的面试问题去理解 提示 请带着这些问 ...
- CMS可视化---ECharts图表
一.ECharts介绍 ECharts,全称Enterprise Charts,商业级数据图表,一个纯Javascript的图表库,能够流畅的运行在PC以及移动设备上,兼容当前绝大部分浏览器.为我们许 ...
- ARL灯塔系统搭建
前言 ARL(Asset Reconnaissance Lighthouse)资产侦查灯塔,是一个良好的资产收集系统,旨在为渗透测试人员以及安全团队基于企业的网络安全能快速查找到指定企业资产中的脆弱点 ...