LM算法
最小二乘法的概念
最小二乘法要关心的是对应的cost function是线性还是非线性函数,不同的方法计算效率如何,要不要求逆,矩阵的维数
一般都是过约束,方程式的数目多于未知的参数数目。
最小二乘法的目标:求误差的最小平方和,根据cost function的对应有两种:线性和非线性(取决于对应的残差(residual)是线性的还是非线性的)。
线性最小二乘的解是closed-form solution 即 \(x = (A^TA)^{-1}A^Tb\)
\(S(x) = ||b -Ax ||^2 = (b -Ax)^T(b -Ax) = b^Tb - b^TAx - x^TA^Tb + x^TA^TAx\)
Note that :\((b^TAx)^T = x^TA^Tb\) 的维数是 1*1(y的列数目).所以 \(b^TAx = x^TA^Tb\)
\(S(x) = b^Tb - 2b^TAx + x^TA^TAx\)
对\(x\)求导
\(-2A^Tb + 2 (A^TA)x = 0\)
\(x = (A^TA)^{-1}A^Tb\)
而非线性最小二乘没有closed-form,通常用迭代法求解。在每次迭代的过程使用一个线性化的方程代替计算。
有牛顿法,牛顿高斯法,LM, 其实可以分为trust region 和 linear line search
非线性最小二乘法的方法有
迭代法,即在每一步update未知量逐渐逼近解,cost function在下降,可以用于各种各样的问题。
- 梯度下降(最速下降法)是迭代法的一种,可以用于求解最小二乘问题
\(f(x + \alpha \overrightarrow d) = f(x_0) + \alpha f'(x_0)\overrightarrow d + \text {二阶以上无穷小}\)
上面的\(x_0\)是泰勒展开式的点, \(\alpha\)是 步长(一个实数) , $ \overrightarrow d$ 单位方向(一个向量),即 \(|\overrightarrow d| = 1\)
显然当\(d\)的方向和\(f'(x_0)\)方向相反的时候,\(cos180 =-1\),整体取到最小值。这就是为什么取的是梯度的反方向原因。
当然上面的步长一般也是可以求得,怎么求步长也是一门学问。
下面的都是从牛顿法引申出来的,记住牛顿法求得是稳定点\(f'(x) = 0\),导数为0的不一定是最小值,梯度下降法求得是局部最小值,从计算上看
- 牛顿法 泰勒展开式到二阶,
\]
求导就有,\(\frac{\partial f}{\partial x_t} = g + H(x_{t+1} -x_t)\),让他为0,就有了牛顿公式
\]
要是H是正定的,上面的就是凸函数,也就一定有了最小值。可惜H不一定是正定的,这就引导出了下面的方法
- 高斯-牛顿法
是另一种经常用于求解非线性最小二乘的迭代法(一定程度上可视为标准非线性最小二乘求解方法)。
我们优化的cost function是 $$min \sum _i r_i(x)^2$$
根据上面的牛顿法:
\]
梯度的表示
\]
Hessian矩阵的表示
\]
要是把上面公式的最后一项去掉,至少是半正定了,而且不用计算Hessain矩阵了,这就是牛顿高斯法
\]
在什么情况下,去掉最后一项比较好,
- residual(\(r_i\))小的时候
- 或者接近linear ,这样一阶微分是常数,二阶微分就是0
上面两种情况下,第二项都很小,公式如下
\]
- Levenberg-Marquardt
的迭代法用于求解非线性最小二乘问题,就结合了梯度下降和高斯-牛顿法。
\]
\]
总结
所以如果把最小二乘看做是优化问题的话,那么梯度下降是求解方法的一种,\(x=(A^TA)^{-1}A^Tb\)是求解线性最小二乘的一种,高斯-牛顿法和Levenberg-Marquardt则能用于求解非线性最小二乘。
LM算法相对于高斯牛顿算法和梯度下降的优缺点
首先梯度下降法和高斯牛顿法都是最优化方法。其区别之处在于,
梯度下降法在寻找目标函数极小值时,是沿着反梯度方向进行寻找的。梯度的定义就是指向标量场增长最快的方向,在寻找极小值时,先随便定初始点(x0,y0)然后进行迭代不断寻找直到梯度的模达到预设的要求。但是梯度下降法的缺点之处在于:在远离极小值的地方下降很快,而在靠近极小值的地方下降很慢,靠近的时候可能成zig-zag下降。
而高斯牛顿法是一种非线性最小二乘最优化方法。其利用了目标函数的泰勒展开式把非线性函数的最小二乘化问题化为每次迭代的线性函数的最小二乘化问题。高斯牛顿法的缺点在于:若初始点距离极小值点过远,迭代步长过大会导致迭代下一代的函数值不一定小于上一代的函数值。
LM算法在高斯牛顿法中加入了因子
μ,当μ大时相当于梯度下降法,μ小时相当于高斯牛顿法。在使用Levenberg-Marquart时,先设置一个比较小的μ值,当发现目标函数反而增大时,将μ增大使用梯度下降法快速寻找,然后再将μ减小使用牛顿法进行寻找。
The Gauss–Newton algorithm is used to solve non-linear least squares problems.
It is a modification of Newton's method for finding a minimum of a function.
Unlike Newton's method, the Gauss–Newton algorithm can only be used to minimize a sum
of squared function values, but it has the advantage that second derivatives, which
can be challenging to compute, are not required.
However, as for many fitting algorithms, the LMA finds only a local minimum,
which is not necessarily the global minimum.
% 计算函数f的雅克比矩阵
syms a b y x real;
f=a*cos(b*x) + b*sin(a*x)
Jsym=jacobian(f,[a b])
data_1=[ 0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0,3.2, 3.4, 3.6, 3.8, 4.0, 4.2, 4.4, 4.6, 4.8, 5.0, 5.2, 5.4, 5.6, 5.8, 6.0, 6.2 ];
obs_1=[102.225 ,99.815,-21.585,-35.099, 2.523,-38.865,-39.020, 89.147, 125.249,-63.405, -183.606, -11.287,197.627, 98.355, -131.977, -129.887, 52.596, 101.193,5.412, -20.805, 6.549, -40.176, -71.425, 57.366, 153.032,5.301, -183.830, -84.612, 159.602, 155.021, -73.318, -146.955];
% 2. LM算法
% 初始猜测初始点
a0=100; b0=100;
y_init = a0*cos(b0*data_1) + b0*sin(a0*data_1);
% 数据个数
Ndata=length(obs_1);
% 参数维数
Nparams=2;
% 迭代最大次数
n_iters=60;
% LM算法的阻尼系数初值
lamda=0.1;
%LM算法的精度
ep=100
% step1: 变量赋值
updateJ=1;
a_est=a0;
b_est=b0;
% step2: 迭代
for it=1:n_iters
if updateJ==1
% 根据当前估计值,计算雅克比矩阵
J=zeros(Ndata,Nparams);
for i=1:length(data_1)
J(i,:)=[cos(b_est*data_1(i))+data_1(i)*b_est*cos(a_est*data_1(i)) -sin(b_est*data_1(i))*a_est*data_1(i)+sin(a_est*data_1(i)) ];
end
% 根据当前参数,得到函数值
y_est = a_est*cos(b_est*data_1) + b_est*sin(a_est*data_1);
% 计算误差
d=obs_1-y_est;
% 计算(拟)海塞矩阵
H=J'*J;
% 若是第一次迭代,计算误差
if it==1
e=dot(d,d);
end
end
% 根据阻尼系数lamda混合得到H矩阵
H_lm=H+(lamda*eye(Nparams,Nparams));
% 计算步长dp,并根据步长计算新的可能的\参数估计值
dp=inv(H_lm)*(J'*d(:));
%求误差大小
g = J'*d(:);
a_lm=a_est+dp(1);
b_lm=b_est+dp(2);
% 计算新的可能估计值对应的y和计算残差e
y_est_lm = a_lm*cos(b_lm*data_1) + b_lm*sin(a_lm*data_1);
d_lm=obs_1-y_est_lm;
e_lm=dot(d_lm,d_lm);
% 根据误差,决定如何更新参数和阻尼系数
if e_lm<e
if e_lm<ep
break
else
lamda=lamda/5;
a_est=a_lm;
b_est=b_lm;
e=e_lm;
disp(e);
updateJ=1;
end
else
updateJ=0;
lamda=lamda*5;
end
end
%显示优化的结果
a_est
b_est
plot(data_1,obs_1,'r')
hold on
plot(data_1,a_est*cos(b_est*data_1) + b_est*sin(a_est*data_1),'g')

#pragma once
#include <stdio.h>
#include <opencv2\core\core.hpp>
#include <iostream>
using namespace std;
using namespace cv;
const int MAXTIME = 50;
#pragma comment(lib,"opencv_core249d.lib")
Mat cvSinMat(Mat a)
{
int rows = a.rows;
int cols = a.cols;
Mat out(rows, cols, CV_64F);
for (int i = 0; i < rows; i++)
{
out.at<double>(i, 0) = sin(a.at<double>(i, 0));
}
return out;
}
Mat cvCosMat(Mat a)
{
int rows = a.rows;
int cols = a.cols;
Mat out(rows, cols, CV_64F);
for (int i = 0; i < rows; i++)
{
out.at<double>(i, 0) = cos(a.at<double>(i, 0));
}
return out;
}
Mat jacobin(const Mat& pk, const Mat& x) // pk= [a,b] a*cos(b*x) + b*sin(a*x)
{
Mat_<double> J(x.rows, pk.rows), Sa, Sb ,Ca, Cb,da, db;
Sa = cvSinMat(pk.at<double>(0)*x);
Sb = cvSinMat(pk.at<double>(1)*x);
Ca = cvCosMat(pk.at<double>(0)*x);
Cb = cvCosMat(pk.at<double>(1)*x);
da = Cb + x.mul(pk.at<double>(1)*Ca);
db = Sa - x.mul(pk.at<double>(0)*Sb);
//cout << "da= " << da << endl;
da.copyTo(J(Rect(0, 0, 1, J.rows)));
db.copyTo(J(Rect(1,0, 1, J.rows)));
return J;
}
Mat yEstimate(const Mat& pk, const Mat& x)
{
Mat_<double> Y(x.rows, x.cols),Cb,Sa;
Sa = cvSinMat(pk.at<double>(0)*x);
Cb = cvCosMat(pk.at<double>(1)*x);
Y = pk.at<double>(0)*Cb + pk.at<double>(1)*Sa;
return Y;
}
void LM(double* p0, int pN, double* x, int xN, double* y, double lamda, double step, double ep = 0.000001)
{
int iters = 0;
int updateJ = 1;
double ek = 0.0, ekk = 0.0;//估计误差
Mat_<double> xM(xN, 1, x), yM(xN, 1, y), pM(pN, 1, p0), JM, yEM, yEMM, dM, gM, dMM, dpM;//至少需要JM,gM,dpM,pM
for (; iters < MAXTIME; iters++)
{
if (updateJ == 1)
{
JM = jacobin(pM, xM); //雅克比矩阵
//outData(fs, JM, "J.xml");
yEM = yEstimate(pM, xM); //f(β)
dM = yM - yEM; // y-f(β)
gM = JM.t()*dM; //
if (iters == 0)
ek = dM.dot(dM); //第一次 直接||r||^2
}
Mat_<double> NM = JM.t()*JM + lamda*(Mat::eye(pN, pN, CV_64F)); //J(T)J + lambda*I
if (solve(NM, gM, dpM)) //
{
Mat_<double> pMM = pM + dpM; //更新最小值
yEMM = yEstimate(pMM, xM);
dMM = yM - yEMM;
ekk = dMM.dot(dMM);
if (ekk < ek)//成功则更新向量与估计误差
{
printf("the %d iterator ,ekk=%lf \n", iters,ekk);
if (dpM.dot(dpM) < ep)
{
printf("Final result is :\n");
printf("精度:0.000001\n");
printf("a =%lf , b=%lf\n", pMM.at<double>(0),pMM.at<double>(1));
return;
}
else
{
pM = pMM;
ek = ekk;
lamda = lamda / step;
updateJ = 1;
continue;
}
}
else //if an iteration gives insufficient reduction in the residual, λ(lamda) can be increased
{
printf("the %d iterator \n", iters);
lamda = lamda*step;
updateJ = 0;
}
}
else
{
printf("the solve invertx matrix error\n");
}
}
}
#include "LM.h"
int main()
{
double data[] = { 0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0,
3.2, 3.4, 3.6, 3.8, 4.0, 4.2, 4.4, 4.6, 4.8, 5.0, 5.2, 5.4, 5.6, 5.8, 6.0, 6.2 };
double obs[] = { 102.225 ,99.815,-21.585,-35.099, 2.523,-38.865,
-39.020, 89.147, 125.249,-63.405, -183.606, -11.287,
197.627, 98.355, -131.977, -129.887, 52.596, 101.193,
5.412, -20.805, 6.549, -40.176, -71.425, 57.366, 153.032,
5.301, -183.830, -84.612, 159.602, 155.021, -73.318, -146.955 };
//初始点
double p0[] = { 100, 100 };
LM(p0, 2, data, 32, obs, 0.1, 10);
system("pause");
}

LM算法的更多相关文章
- LM算法与非线性最小二乘问题
摘录的一篇有关求解非线性最小二乘问题的算法--LM算法的文章,当中也加入了一些我个人在求解高精度最小二乘问题时候的一些感触: LM算法,全称为Levenberg-Marquard算法,它可用于解决非线 ...
- Levenberg-Marquardt迭代(LM算法)-改进Guass-Newton法
1.前言 a.对于工程问题,一般描述为:从一些测量值(观测量)x 中估计参数 p?即x = f(p), ...
- LM算法的推导过程
- 梯度下降法、牛顿法、高斯牛顿法、LM最优化算法
1.梯度下降法 2.牛顿法 3.高斯牛顿法 4.LM算法
- Levenberg-Marquardt优化算法以及基于LM的BP-ANN
一.LM最优化算法 最优化是寻找使得目标函数有最大或最小值的的参数向量.根据求导数的方法,可分为2大类.(1)若f具有解析函数形式,知道x后求导数速度快.(2)使用数值差分来求导数.根据使用模 ...
- LM拟合算法
一. Levenberg-Marquardt算法 (1)y=a*e.^(-b*x)形式拟合 clear all % 计算函数f的雅克比矩阵,是解析式 syms a b y x real; f=a*e ...
- Levenberg-Marquardt算法基础知识
Levenberg-Marquardt算法基础知识 (2013-01-07 16:56:17) 转载▼ 什么是最优化?Levenberg-Marquardt算法是最优化算法中的一种.最优化是寻找使 ...
- 相机标定:关于用Levenberg-Marquardt算法在相机标定中应用
LM算法在相机标定的应用共有三处. (1)单目标定或双目标定中,在内参固定的情况下,计算最佳外参.OpenCV中对应的函数为findExtrinsicCameraParams2. (2)单目标定中,在 ...
- 点云匹配和ICP算法概述
Iterative Closest Point (ICP) [1][2][3] is an algorithm employed to minimize the difference between ...
随机推荐
- Android 高级UI设计笔记06:仿微信图片选择器(转载)
仿微信图片选择器: 一.项目整体分析: 1. Android加载图片的3个目标: (1)尽可能的去避免内存溢出. a. 根据图片的显示大小去压缩图片 b. 使用缓存对我们图片进行管理(LruCache ...
- iOS之Xcode8 Auto Layout新特性
目录 1.Incrementally Adopting Auto Layout 2.Design and Runtime Constraints 3.NSGridView 4.Layout Feedb ...
- HTML5 indexedDB数据库的入门学习(二)
上一篇关于indexedDB的学习笔记主要写了indexedDB数据库的基本操作—增删改查:但是为什么我们要用indexedDB呢?为什么indexedDB受到了开发者们的青睐呢?最主要的就是inde ...
- [转]bat批处理实现TXT文本合并
本文转自:http://quanhuaming.blog.163.com/blog/static/1405693672010210101124905/ 有朋友问是否有可以合并TXT文本文件的软件,于是 ...
- Windows 7 IE11 F12 不能正常使用
打开任意网站,按下F12,或者右键鼠标,按L键.出现上面的图的情况!解决办法如下:需要安装下面的补丁(KB3008923) 32位系统:http://www.microsoft.com/en-us/d ...
- 为EditText设置OnTouchListener事件监听
在项目中需要在EditText输入前,判断某个值是否已经有值,有才可以输入,为NULL值则提示不让输入,先填写指定的编辑框 自己试过监听获取焦点事件,来设置setFocusable(true)或者se ...
- 【转载】Android设计中的.9.png
转载自:腾讯ISUX (http://isux.tencent.com/android-ui-9-png.html) 在Android的设计过程中,为了适配不同的手机分辨率,图片大多需要拉伸或者压 ...
- Android OOM 解决方案
Out of Memory(内存溢出) 几乎是每个Android程序员都会遇到的事.在网上也能找到一大堆的解决方案,之前写过一篇<Android 内存溢出管理与测试>的博文.但感觉写得不是 ...
- ubuntu(16.04.01)学习-day2--高级命令
1.查找命令 find -name "hello.c" grep "test" grep "usb" -c -r /drivers/usb ...
- 腾讯QQ群数据下载方法(7000万个qq群资料全泄漏)
仔细读完一定能找到自己需要的东西 据新华网报道,国内知名安全漏洞监测平台乌云20日公布报告称,腾讯QQ群关系数据被泄露,网上可以轻易就能找到数据下载链接,根据这些数据,通过QQ号可以查询到备注姓名.年 ...
