优化算法学习(LM算法)

2023-11-15

推荐书籍

建议学习,METHODS FOR NON-LINEAR LEAST SQUARES PROBLEMS:
http://www2.imm.dtu.dk/pubdb/views/edoc_download.php/3215/pdf/imm3215.pdf
篇幅不长,容易理解
学习的时候可以参考另一篇,UNCONSTRAINED OPTIMIZATION:http://www2.imm.dtu.dk/pubdb/views/edoc_download.php/3217/pdf/imm3217.pdf

Numerical Optimization 2nd --Jorge Nocedal Stephen J. Wright:
http://www.bioinfo.org.cn/~wangchao/maa/Numerical_Optimization.pdf
《视觉SLAM十四讲》第六讲 https://github.com/gaoxiang12/slambook

理论理解

知乎上看到一个回答非常好:

LM算法可以理解为Gauss-Newton算法与最速下降法的结合,如果理解了如何用上述算法求解目标函数最小值的问题,自然也能理解LM。

其实算法的本质就是 a. 站在当前位置( x k x_k xk ),我们需要一个预言(oracle)告诉我们往哪走能找到目的地(最优解可能的方向,比如梯度方向);b. 我们沿着该方向走了一段距离之后(stepsize),更新当前位置信息( x k + 1 x_{k+1} xk+1 ),再问预言家我们下一步往哪走,以此反复。

所以,梯度下降法,给的 oracle 就是当前位置的梯度信息(损失方程关于变量的一阶导数):

x k + 1 = x k − α g k x_{k+1}=x_k-\alpha g_k xk+1=xkαgk

如果是牛顿法,给的 oracle 就是Hessian matrix(损失方程关于变量的二阶导数):

x k + 1 = x k − H k − 1 g k x_{k+1}=x_k-H_k^{-1}g_k xk+1=xkHk1gk(1)

为什么是一阶导数和二阶导数?因为我们知道,对于任意(处处可导的)方程,在其任意一点,我们都可以用泰勒展开式对其拟合,阶数越高,精度越高。但是,考虑到高阶导数的计算复杂度,以及三阶以上函数的非凸性,也不会使用高阶导数。

好了,那么LM算法的优势是什么?牛顿法虽然收敛速度快,但是需要计算 Hessian matrix,对于高维的问题,计算二阶导数会很复杂。因此我们有了Gauss-Newton算法。Gauss-Newton算法不直接计算Hessian matrix,而是通过 Jacobian matrix 对 Hessian matrix 进行拟合:

H ≈ J T J H\approx J^TJ HJTJ

但是,用 Jacobian matrix 拟合Hessian matrix,所计算出来的结果不一定可逆。所以在此基础上,我们引入了一个identity matrix:

H ≈ J T J + μ I H\approx J^TJ+\mu I HJTJ+μI

这也就得到了LM算法。如果我们把上述式子带入之前的公式(1),可以得到

x k + 1 = x k − ( J k T J k + μ I ) − 1 g k x_{k+1}=x_k-(J_k^TJ_k+\mu I)^{-1}g_k xk+1=xk(JkTJk+μI)1gk

所以我们发现,当 μ \mu μ接近于0时,这个算法近似于Gauss-Newton算法;当 μ \mu μ很大时,这个算法近似于最速下降法。因此,这也是为什么LM算法称为Gauss-Newton算法与最速下降法的结合。最后,上一张图表示几种算法之间的关系:
在这里插入图片描述
参考文献:Wilamowski, B. M., & Yu, H. (2010). Improved computation for Levenberg–Marquardt training. IEEE transactions on neural networks, 21(6), 930-937.

一个回答:Matlab 的话现成的代码也是很多的;比如,Solve nonlinear least-squares (nonlinear data-fitting) problems,或者 Levenberg-Marquardt-Fletcher algorithm for nonlinear least squares problems。你可以在网站里面搜搜有没有适合你的。

作者:Sixiang
链接:https://www.zhihu.com/question/269579938/answer/349205519
来源:知乎

这是最上面推荐的书,英文不难:
在这里插入图片描述

gradient matrix, hessian matrix, jacobian matrix:gradient hessian jacobian matrix
https://www.value-at-risk.net/functions/

csdn 有个不错的博客:数值优化(Numerical Optimization)学习系列-目录:https://blog.csdn.net/fangqingan_java/article/details/48951191

程序实现

视觉SLAM十四讲里推荐了**Ceres库**,Ceres solver 是谷歌开发的一款用于非线性优化的库,在谷歌的开源激光雷达slam项目cartographer中被大量使用。
安装和使用参考:
https://zhaoxuhui.top/blog/2018/04/04/ceres&ls.html
下面把关键操作贴出来:

ceres安装

  • 下载源码
    git clone https://github.com/ceres-solver/ceres-solver.git
  • 安装依赖:
sudo apt-get install cmake
# google-glog + gflags
sudo apt-get install libgoogle-glog-dev libgtest-dev libgflags-dev
# BLAS & LAPACK
sudo apt-get install libatlas-base-dev liblapack-dev
# Eigen3
sudo apt-get install libeigen3-dev
# SuiteSparse and CXSparse (optional)
sudo apt-get install libsuitesparse-dev libcxsparse3.1.4

这里libcxsparse可能存在版本问题(出现找不到对应版本),解决办法:

sudo apt-get install bash-completion
sudo gedit /etc/bash.bashrc

将这一部分取消注释,并保存,即可自动补全:
在这里插入图片描述
sudo apt-get install libsuitesparse-dev libcxsparse(按tab)

cd ceres-solver/
mkdir build
cd build
cmake ..
make -j3
sudo make install

代码:

利用Ceres简单实现最小二乘曲线拟合。首先需要生成数据,这里采用OpenCV的随机数生成器生成误差。

#include <iostream>
#include <opencv2/core/core.hpp>
#include <ceres/ceres.h>

using namespace std;
using namespace cv;
using namespace ceres;

//vector,用于存放x、y的观测数据
//待估计函数为y=3.5x^3+1.6x^2+0.3x+7.8
vector<double> xs;
vector<double> ys;

//定义CostFunctor结构体用于描述代价函数
struct CostFunctor{
  
  double x_guan,y_guan;
  
  //构造函数,用已知的x、y数据对其赋值
  CostFunctor(double x,double y)
  {
    x_guan = x;
    y_guan = y;
  }
  
  //重载括号运算符,两个参数分别是估计的参数和由该参数计算得到的残差
  //注意这里的const,一个都不能省略,否则就会报错
  template <typename T>
  bool operator()(const T* const params,T* residual)const
  {
    residual[0]=y_guan-(params[0]*x_guan*x_guan*x_guan+params[1]*x_guan*x_guan+params[2]*x_guan+params[3]);
    return true;  
  }
};

//生成实验数据
void generateData()
{
  RNG rng;
  //RNG::gaussian( σ) 返回一个均值为0,标准差为σ的随机数。
  double w_sigma = 1.0;
  for(int i=0;i<100;i++)
  {
    double x = i;
    double y = 3.5*x*x*x+1.6*x*x+0.3*x+7.8;
    xs.push_back(x);
    ys.push_back(y+rng.gaussian(w_sigma));
  }
  for(int i=0;i<xs.size();i++)
  {
    cout<<"x:"<<xs[i]<<" y:"<<ys[i]<<endl;
  }
}

//简单描述我们优化的目的就是为了使我们估计参数算出的y'和实际观测的y的差值之和最小
//所以代价函数(CostFunction)就是y'-y,其对应每一组观测值与估计值的残差。
//由于我们优化的是残差之和,因此需要把代价函数全部加起来,使这个函数最小,而不是单独的使某一个残差最小
//默认情况下,我们认为各组的残差是等权的,也就是核函数系数为1。
//但有时可能会出现粗差等情况,有可能不等权,但这里不考虑。
//这个求和以后的函数便是我们优化的目标函数
//通过不断调整我们的参数值,使这个目标函数最终达到最小,即认为优化完成
int main(int argc, char **argv) {
  
  generateData();
  
  //创建一个长度为4的double数组用于存放参数
  double params[4]={1.0};

  //第一步,创建Problem对象,并对每一组观测数据添加ResidualBlock
  //由于每一组观测点都会得到一个残差,而我们的目的是最小化所有残差的和
  //所以采用for循环依次把每个残差都添加进来
  Problem problem;
  for(int i=0;i<xs.size();i++)
  {
    //利用我们之前写的结构体、仿函数,创建代价函数对象,注意初始化的方式
    //尖括号中的参数分别为误差类型,输出维度(因变量个数),输入维度(待估计参数的个数)
    CostFunction* cost_function = new AutoDiffCostFunction<CostFunctor,1,4>(new CostFunctor(xs[i],ys[i]));
    //三个参数分别为代价函数、核函数和待估参数
    problem.AddResidualBlock(cost_function,NULL,params);
  }
  
  //第二步,配置Solver
  Solver::Options options;
  //配置增量方程的解法
  options.linear_solver_type=ceres::DENSE_QR;
  //是否输出到cout
  options.minimizer_progress_to_stdout=true;
  
  //第三步,创建Summary对象用于输出迭代结果
  Solver::Summary summary;
  
  //第四步,执行求解
  Solve(options,&problem,&summary);
  
  //第五步,输出求解结果
  cout<<summary.BriefReport()<<endl;
  
  cout<<"p0:"<<params[0]<<endl;
  cout<<"p1:"<<params[1]<<endl;
  cout<<"p2:"<<params[2]<<endl;
  cout<<"p3:"<<params[3]<<endl;
  return 0;
}

CMakeLists.txt:

cmake_minimum_required(VERSION 2.6)
project(ceres_test)

set( CMAKE_CXX_FLAGS "-std=c++11 -O3" )

# 添加cmake模块以使用ceres库
list( APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake_modules )

# 寻找Ceres库并添加它的头文件
find_package( Ceres REQUIRED )
include_directories( ${CERES_INCLUDE_DIRS} )

# OpenCV
find_package( OpenCV REQUIRED )
include_directories( ${OpenCV_DIRS} )

add_executable(ceres_test main.cpp)

# 与Ceres和OpenCV链接
target_link_libraries( ceres_test ${CERES_LIBRARIES} ${OpenCV_LIBS} )

install(TARGETS ceres_test RUNTIME DESTINATION bin)

另外,有个levmar的C/C++的库:(这个还不会用)
levmar : Levenberg-Marquardt nonlinear least squares algorithms in C/C++
http://users.ics.forth.gr/~lourakis/levmar/index.html#download
http://users.ics.forth.gr/~lourakis/sparseLM/

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

优化算法学习(LM算法) 的相关文章

  • 大话算法之动态规划——初探

    对于动态规划 之前学习过了 但是总感觉理解不深刻 今天正好讲道动态规划算法 感觉有了一些新的认识和看法 打算详细的写下来 一是帮助自己理清 二是希望给刚刚接触的ACMer一个简明的理解思路吧 大话算法之动态规划 初探 一 引例 数塔问题 之
  • 【算法导论学习】分治法求最大子数组

    最大子数组 分治法 问题分析方向 对时间复杂度的分析 样例分析 问题分析 分解问题 解决问题 合并问题 对代码的设想 中间部分的处理 递归部分 时间复杂度分析 完整代码 分治法 所谓分治法 就是把问题不断分割变小 常见的是把数组分割为两部分
  • 蓝桥杯考前必看知识点【python 代码详解】

    文章目录 前言 一 基本知识点 1 基本输入输出 2 列表转字符串 3 字符串大小写转换 4 匿名函数lambda 5 二 八 十六进制 6 chr ord转换 7 保留小数点后几位 8 排序 二 python常用内置库模块 1 facto
  • 代码随想录一刷-Day08

    Offer58 II 左旋转字符串 使用中间数组很容易 public String reverseLeftWords String s int n if n 0 s null s length 0 return s 使用中间数组 char
  • 前缀和&差分

    前缀和 能快速求出来一段数的和 比如说从 l r 的和 可以说是最大的应用 是个很重要的技巧 下标从1开始 二维前缀和 leedcode练习 724 寻找数组的中心下标 思路 记数组的全部元素之和为 total 当遍历到第 i 个元素时 设
  • 两个有序序列的中位数(详解)

    1 实践题目 7 3 两个有序序列的中位数 2 问题描述 在一行中输出两个输入序列的并集序列的中位数 时间复杂度不能大于O logn 3 算法描述 不能粘贴程序 因为时间复杂度不能大于logn 所以把原序列排好序再来找中位数是不可能的了 快
  • 测试gpt的function函数功能

    官网API 科学上网查看 1 我对该功能的理解 利用gpt的上下文理解能力 在执行方法run conversation xx 时 目标锁定在 提取出functions里每个function下required属性对应的值 而真正的functi
  • 字典排序算法(通俗易懂)

    我们先看一个例子 示例 1 2 3的全排列如下 1 2 3 1 3 2 2 1 3 2 3 1 3 1 2 3 2 1 我们这里是通过字典序法找出来的 那么什么是字典序法呢 从上面的全排列也可以看出来了 从左往右依次增大 对这就是字典序法
  • 刷题之合并二叉树

    给定两个二叉树 想象当你将它们中的一个覆盖到另一个上时 两个二叉树的一些节点便会重叠 你需要将他们合并为一个新的二叉树 合并的规则是如果两个节点重叠 那么将他们的值相加作为节点合并后的新值 否则不为 NULL 的节点将直接作为新二叉树的节点
  • 模型选择、欠拟合和过拟合学习笔记

    训练误差 泛化误差 训练误差 模型在训练数据集上表现出的误差 泛化误差 指模型在任意一个测试数据样本上表现出的误差的期望 并常常通过测试数据集上的误差来近似 过拟合 欠拟合 过拟合 训练误差远小于其在测试数据集上的误差 欠拟合 模型无法得到
  • 完全平方数算法题

    题目描述 对于一个序列 牛牛每次可以将序列中任意一个位置上的数乘上任意一个质数 现在他想知道至少需要多少次操作才能使得该序列中的任意两个不同位置的数相乘都为完全平方数 完全平方数 对于x 若其可以写成 i i x i i x
  • Leetcode刷题笔记0624(回文字符串)

    解题思路 1 首先考虑用双指针 一头一尾依次遍历 遇到相等的l 和r 进入下一层循环 2 遇到不相等的记录值count 1 判断l 与r是否相等 l与r 是否相等 否则直接返回false 形成代码 class Solution public
  • 算法案例:如何判断链表有环?

    本文转载于 算法 如何判断链表有环 如何判断单链表是否存在环 有一个单向链表 链表当中有可能出现 环 就像题图这样 如何用程序判断出这个链表是有环链表 不允许修改链表结构 时间复杂度O n 空间复杂度O 1 方法一 穷举遍历 方法一 首先从
  • 【二维费用的完全背包问题】

    前言 简单写一下算法设计与分析这门课的一次实验 原题要求是用0 1背包来做 但是老师要求用完全背包来做 一 完全背包与0 1背包有什么区别 0 1背包 顾名思义对于每件物品只能拿1次或者0次 而完全背包对于每件物品的拿取没有次数限制 二 二
  • 刷题之轮转数组

    给你一个数组 将数组中的元素向右轮转 k 个位置 其中 k 是非负数 示例 1 输入 nums 1 2 3 4 5 6 7 k 3 输出 5 6 7 1 2 3 4 解释 向右轮转 1 步 7 1 2 3 4 5 6 向右轮转 2 步 6
  • 代码随想录一刷-Day01

    代码随想录一刷 Day01 LeetCode704 二分查找 这道属于是入门必刷了 但是虽然能做出来 在细节上还是不够注意 public int search int nums int target if nums null nums le
  • 两个二叉树的合并

    将给定两个二叉树 想象当你将它们中的一个覆盖到另一个上时 两个二叉树的一些节点便会重叠 你需要将他们合并为一个新的二叉树 合并的规则是如果两个节点重叠 那么将他们的值相加作为节点合并后的新值 否则不为 NULL 的节点将直接作为新二叉树的节
  • 数论算法:唯一因子分解定理

    这里讲一下算法中常用到的唯一因子分解定理 合数a仅能以一种方式写成如下乘积形式 a p1 e1 p2 e2 pr er 其中pi为素数 p1
  • 贪心(acwing)

    每次选择当前的最优解 没什么固定的套路 先试一些做法 举例子验证 尝试证明一下 严格地推 区间问题 例1 1 将每个区间按照右端点从小到大排序 2 从前往后依次枚举每个区间 如果当前区间已经包含点 则直接pass 否则选择当前区间的右端点
  • 用递归法求两个数的最大公约数

    用递归法求两个数的最大公约数 求两个数的最大公约数的思路是 用辗转现除法 辗转相除法求两个数的最大公约数的步骤如下 先用小的一个数除大的一个数 得第一个余数 再用第一个余数除小的一个数 得第二个余数 又用第二个余数除第一个余数 得第三个余数

随机推荐

  • 计算机系统课程 笔记总结 CSAPP第七章 链接(7.1-7.13)

    GitHub计算机系统CSAPP课程资源 计算机系统课程 笔记总结 CSAPP第二章 信息的表示和处理 2 1 2 2 计算机系统课程 笔记总结 CSAPP第二章 信息的表示和处理 2 3 2 4 计算机系统课程 笔记总结 CSAPP第三章
  • Ubuntu复现NeuS(用体绘制学习神经隐式曲面用于多视图重建 )——NeRF应用:表面重建

    目录 一 系统配置 二 安装 可能会遇到的问题 1 pytorch安装报错 2 缺少安装依赖项 三 数据集文件夹设置 1 数据集链接 2 数据集组织 3 以dtu scan24为例 四 训练 以dtu scan24为例 1 无掩码训练 2
  • 在Linux系统中部署zabbix监控服务

    今天学习安装zabbix 以下参考网上各种安装方法及自己做实验 一 zabbix简介 zabbix z biks 是一个基于WEB界面的提供分布式系统监视以及网络监视功能的企业级的开源解决方案 zabbix能监视各种网络参数 保证服务器系统
  • 查找---散列表查找定义

    当我们进行查找时 如果是顺序表查找 要找的关键字的记录 是从表头开始 挨个的比较记录a i 与key的值是等于还是不等于 有序表查找时 利用折半查询或者插值查询 直到相等时成功返回i 最终我们的目的都是为了找到那个i 其实也就是相对的下标
  • 使用TortoiseGit

    初衷 脱离命令行的方式 使用gui的界面化工具完成工作需要的版本控制操作 同时还对git运行机制有一定的了解 达到工作需要的基本 提高工作效率 准备工作 安装git 至于为什么 我就不废话了 点我下载git 安装TortoiseGit 理由
  • 【vue3引入高德地图】

    vue3引入高德地图 文章目录 vue3引入高德地图 前言 一 准备工作 1 开发文档 2 添加应用 二 使用步骤 1 npm 安装 2 地图容器创建 3 组件引入 4 js api 安全密钥 5 初始化地图 6 图层 6 1 添加 设置
  • 在 Windows 10 编译 Qt 5.15

    译好的下载链接 Qt5 15 8 Windows x86 VS2017 Qt5 15 8 Windows x86 64 VS2017 Qt5 15 8 Windows x86 VS2019 Qt5 15 8 Windows x86 64 V
  • 【Unity】通过代码控制编译器的暂停

    暂停编译器 EditorApplication isPaused true 结束编译器 EditorApplication isPlaying false
  • sklearn决策树之random_state & splitter

    在上一篇博文 决策树的sklearn实现 中 我们建立了一棵完整的决策树 但是如果在建立模型时不设置random state的数值 score会在某个值附近波动 引起画出来的每一棵树都 一样 它为什么会 稳定呢 如果使用其他数据集 它还会不
  • 互斥机制之自旋锁(spinlock)

    一 基础 自旋锁 如果测试结果表明锁仍被占用 程序将在一个小的循环内重复这个 测试并设置 操作 即进行所谓的 自旋 1 定义自旋锁 spinlock t spin 2 初始化自旋锁 spin lock init lock 该宏用于动态初始化
  • 【论文笔记】Masked Autoencoders Are Scalable Vision Learners

    论文 论文标题 Masked Autoencoders Are Scalable Vision Learners 发表于 CVPR2021 论文链接 https arxiv org pdf 2111 06377 pdf 论文代码 https
  • WebGL学习系列-片元着色器简介

    前言 到目前为止 我们绘制过点 三角形 矩形等 但使用的都是单色系 之前曾经说过着色器的概念 着色器分为顶点着色器和片元着色器 我们一直在使用顶点着色器 而对片元着色器基本没有提及过 本小节将展开对片元着色器的简单介绍 彩色的点 之前提到过
  • Sybase IQ常用函数大全--杂项函数

    Sybase IQ常用函数大全 杂项函数 查询索引 COALESCE 函数 返回列表中的第一个非 NULL 表达式 IFNULL 函数 返回第一个非空值表达式或 NULL ISNULL 函数 返回参数列表中的第一个非 NULL 表达式的值
  • 笔记~【软件测试基础知识】——黑盒测试和白盒测试

    这里写目录标题 一 黑盒测试 二 白盒测试 一 黑盒测试 黑盒测试概述 黑盒测试也称功能测试或数据驱动测试 它已知产品所应具有的功能 通过测试来检测每个功能是否能够正常使用 主要针对软件界面和软件功能 在测试时 把程序看作一个不能打开的黑盒
  • cv::Mat的翻转和转置

    cv Mat的本质是矩阵 openCV对Mat类型的处理 实际上也是矩阵操作 这里给个小例子 介绍转置操作和翻转操作 这段代码受了 http www tuicool com articles emIr2u 的启发 原图 Mat m1 imr
  • 【数据预处理】Pandas缺失的数据处理

    目录 缺少数据基础 何时 为何 数据丢失 被视为 缺失 的值 日期时间 插入缺失数据 缺少数据的计算 Sum Prod of Empties Nans GroupBy中的NA值 清理 填写缺失数据 填充缺失值 fillna 用PandasO
  • flutter -- 自定义音乐播放器/视频播放器

    写在前头 flutter 自定义实现音乐播放的文章挺多的 但是在开发中还是碰见了超级无语的情况 没想到需求竟然要音频的1倍到2倍的播放倍速 我一度质疑这个功能的实际用途 但是既然提出来了 开发就得撅屁股实现 这里采用了第三方的视频播放器来实
  • 如何使用BurpSuite(后续)

    前面那篇文章是我前几天写的 我发现我把简单的问题弄得复杂了 今天我给大家再写一篇关于BurpSuite的使用 1 下载安装免费版或者收费版 这里就不演示了 2 运行软件 一直NEXT就可以 3 打开工具 此时拦截状态显示OFF 4 在打开的
  • Python中类成员变量与实例成员变量相互影响的原因超详细解释

    今天在看python学习手册时看到了两句话 一 第26章中 类对象提供默认行为 二 第26章中 实例对象是具体的元素 书中给的例子是这样的 但上网查了一下好像第二句话不是非常准确 如下面的文章 原文 https www jb51 net a
  • 优化算法学习(LM算法)

    文章目录 推荐书籍 理论理解 程序实现 ceres安装 代码 推荐书籍 建议学习 METHODS FOR NON LINEAR LEAST SQUARES PROBLEMS http www2 imm dtu dk pubdb views