LM算法原理及其python自定义实现

  • LM(Levenberg–Marquardt)算法原理
  • LM算法python实现
    • 实现步骤:
    • 代码:
    • 运行结果:

LM(Levenberg–Marquardt)算法原理

LM算法作为非线性优化的“标准”方法,算法的数学原理有很多优秀的参考资料。我看过这些参考资料之后,觉得再重新写一遍已经是无力且多余的事情了。我简单说明一下这些参考资料,然后贴上自己的手写笔记。
参考资料:
1.《Methods for non-linear least squares problems》这本书将非线性最小二乘问题的优化方法讲了一大通,非常值得一看。因为LM算法是从Gauss-Newton方法演进来的,而Gauss-Newton方法又是从Newton方法演进过来的,所以追根溯源应该从Newton法开始看起。而比Newton法更简洁的就是最速下降法了,这本书将所有的非线性优化问题讲了个底朝天,聪明人仔细读一读不吃亏。
2.A Brief Description of the Levenberg-Marquardt Algorithm Implemened by levmar
如果说上面那本书是准备好给搞理论看的版本的话,那这篇文章一定就是准备好给工程师看的了,文章对LM算法的实现给出了很好的讲解,工程师读一下,醍醐灌顶就可以写代码了。
3.[blog]原理及C++实现:Levenberg–Marquardt算法学习
4.[blog]原理及matlab实现:Levenberg-Marquardt
5.[blog]另一篇python实现:Python 算例实现Levenberg-Marquardt算法
6.我的笔记,你可以放心略过的部分:)D

LM算法python实现

实现步骤:

在LM算法原理中提到的参考资料提供了一些算法实现的伪代码,但是他们略有不同,主要的不同点是在公式表述以及u、v的更新比率上有小的差异。
我运行过他们的部分代码,发现优化效果也能够快速收敛,并不影响实际效果。
我按照文章A Brief Description of the Levenberg-Marquardt Algorithm Implemened by levmar中的步骤,重新写了python代码,代码实现步骤如下:

代码:

1.我随机产生了100个input_data,设定正确的参数a和b,然后按照我要拟合的公式a×np.exp(b×input_data)加上一些高斯噪声计算出了100个对应的output_data, 作为观察。
2.初始化参数a和b,使之不要与真实值太离谱
3.用LM算法对其优化拟合,画出拟合曲线和迭代误差曲线。

'''
#Implement LM algorithm only using basic python
#Author:Leo Ma
#For csmath2019 assignment4,ZheJiang University
#Date:2019.04.28
'''
import numpy as np
import matplotlib.pyplot as plt #input data, whose shape is (num_data,1)
#data_input=np.array([[0.25, 0.5, 1, 1.5, 2, 3, 4, 6, 8]]).T
#data_output=np.array([[19.21, 18.15, 15.36, 14.10, 12.89, 9.32, 7.45, 5.24, 3.01]]).Ttao = 10**-3
threshold_stop = 10**-15
threshold_step = 10**-15
threshold_residual = 10**-15
residual_memory = []#construct a user function
def my_Func(params,input_data):a = params[0,0]b = params[1,0]#c = params[2,0]#d = params[3,0]return a*np.exp(b*input_data)#return a*np.sin(b*input_data[:,0])+c*np.cos(d*input_data[:,1])#generating the input_data and output_data,whose shape both is (num_data,1)
def generate_data(params,num_data):x = np.array(np.linspace(0,10,num_data)).reshape(num_data,1)       # 产生包含噪声的数据mid,sigma = 0,5y = my_Func(params,x) + np.random.normal(mid, sigma, num_data).reshape(num_data,1)return x,y#calculating the derive of pointed parameter,whose shape is (num_data,1)
def cal_deriv(params,input_data,param_index):params1 = params.copy()params2 = params.copy()params1[param_index,0] += 0.000001params2[param_index,0] -= 0.000001data_est_output1 = my_Func(params1,input_data)data_est_output2 = my_Func(params2,input_data)return (data_est_output1 - data_est_output2) / 0.000002#calculating jacobian matrix,whose shape is (num_data,num_params)
def cal_Jacobian(params,input_data):num_params = np.shape(params)[0]num_data = np.shape(input_data)[0]J = np.zeros((num_data,num_params))for i in range(0,num_params):J[:,i] = list(cal_deriv(params,input_data,i))return J#calculating residual, whose shape is (num_data,1)
def cal_residual(params,input_data,output_data):data_est_output = my_Func(params,input_data)residual = output_data - data_est_outputreturn residual'''
#calculating Hessian matrix, whose shape is (num_params,num_params)
def cal_Hessian_LM(Jacobian,u,num_params):H = Jacobian.T.dot(Jacobian) + u*np.eye(num_params)return H#calculating g, whose shape is (num_params,1)
def cal_g(Jacobian,residual):g = Jacobian.T.dot(residual)return g#calculating s,whose shape is (num_params,1)
def cal_step(Hessian_LM,g):s = Hessian_LM.I.dot(g)return s'''#get the init u, using equation u=tao*max(Aii)
def get_init_u(A,tao):m = np.shape(A)[0]Aii = []for i in range(0,m):Aii.append(A[i,i])u = tao*max(Aii)return u#LM algorithm
def LM(num_iter,params,input_data,output_data):num_params = np.shape(params)[0]#the number of paramsk = 0#set the init iter count is 0#calculating the init residualresidual = cal_residual(params,input_data,output_data)#calculating the init Jocobian matrixJacobian = cal_Jacobian(params,input_data)A = Jacobian.T.dot(Jacobian)#calculating the init Ag = Jacobian.T.dot(residual)#calculating the init gradient gstop = (np.linalg.norm(g, ord=np.inf) <= threshold_stop)#set the init stopu = get_init_u(A,tao)#set the init uv = 2#set the init v=2while((not stop) and (k<num_iter)):k+=1while(1):Hessian_LM = A + u*np.eye(num_params)#calculating Hessian matrix in LMstep = np.linalg.inv(Hessian_LM).dot(g)#calculating the update stepif(np.linalg.norm(step) <= threshold_step):stop = Trueelse:new_params = params + step#update params using stepnew_residual = cal_residual(new_params,input_data,output_data)#get new residual using new paramsrou = (np.linalg.norm(residual)**2 - np.linalg.norm(new_residual)**2) / (step.T.dot(u*step+g))if rou > 0:params = new_paramsresidual = new_residualresidual_memory.append(np.linalg.norm(residual)**2)#print (np.linalg.norm(new_residual)**2)Jacobian = cal_Jacobian(params,input_data)#recalculating Jacobian matrix with new paramsA = Jacobian.T.dot(Jacobian)#recalculating Ag = Jacobian.T.dot(residual)#recalculating gradient gstop = (np.linalg.norm(g, ord=np.inf) <= threshold_stop) or (np.linalg.norm(residual)**2 <= threshold_residual)u = u*max(1/3,1-(2*rou-1)**3)v = 2else:u = u*vv = 2*vif(rou > 0 or stop):break;return paramsdef main():#set the true params for generate_data() functionparams = np.zeros((2,1))params[0,0]=10.0params[1,0]=0.8num_data = 100# set the data numberdata_input,data_output = generate_data(params,num_data)#generate data as requested#set the init params for LM algorithm params[0,0]=6.0params[1,0]=0.3#using LM algorithm estimate paramsnum_iter=100    # the number of iterationest_params = LM(num_iter,params,data_input,data_output)print(est_params)a_est=est_params[0,0]b_est=est_params[1,0]#老子画个图看看状况plt.scatter(data_input, data_output, color='b')x = np.arange(0, 100) * 0.1 #生成0-10的共100个数据,然后设置间距为0.1plt.plot(x,a_est*np.exp(b_est*x),'r',lw=1.0)plt.xlabel("2018.06.13")plt.savefig("result_LM.png")plt.show()plt.plot(residual_memory)plt.xlabel("2018.06.13")plt.savefig("error-iter.png")plt.show()if __name__ == '__main__':main()

运行结果:

LM(Levenberg–Marquardt)算法原理及其python自定义实现相关推荐

  1. 手写系列之手写LM(Levenberg–Marquardt)算法(基于eigen)

    紧接上次的手写高斯牛顿,今天顺便将LM算法也进行了手写实现,并且自己基于eigen的高斯牛顿进行了对比,可以很明显的看到,LM的算法收敛更快,精度也略胜一筹,这次高博的书不够用了,参考网上伪代码进行实 ...

  2. Levenberg–Marquardt算法学习

    本次是对Levenberg–Marquardt的学习总结,是为之后看懂sparse bundle ajdustment打基础.这篇笔记包含如下内容: 回顾高斯牛顿算法,引入LM算法 惩罚因子的计算(迭 ...

  3. 手把手教你EMD算法原理与Python实现(更新)

    Rose今天主要介绍一下EMD算法原理与Python实现.关于EMD算法之前介绍过<EMD算法之Hilbert-Huang Transform原理详解和案例分析>, SSVEP信号中含有自 ...

  4. python kmeans聚类 对二维坐标点聚类_Kmeans均值聚类算法原理以及Python如何实现

    第一步.随机生成质心 由于这是一个无监督学习的算法,因此我们首先在一个二维的坐标轴下随机给定一堆点,并随即给定两个质心,我们这个算法的目的就是将这一堆点根据它们自身的坐标特征分为两类,因此选取了两个质 ...

  5. 匈牙利算法原理与Python实现

    匈牙利算法原理与Python实现 今天学习一个新的算法-匈牙利算法,用于聚类结果分析,先用图表示我当前遇到的问题: 这两列值是我用不同算法得到的聚类结果,从肉眼可以看出第一列聚类为0的结果在第二列中对 ...

  6. Apriori 算法原理以及python实现详解

    Apriori 算法原理以及python实现 ​ Apriori算法是第一个关联规则挖掘算法,也是最经典的算法.它利用逐层搜索的迭代方法找出数据库中项集的关系,以形成规则,其过程由连接(类矩阵运算)与 ...

  7. PageRank算法原理与Python实现

    本文转载自https://blog.csdn.net/ten_sory/article/details/80927738 PageRank算法原理与Python实现 PageRank算法,即网页排名算 ...

  8. 非线性最小二乘问题与Levenberg–Marquardt算法详解

    1 最小二乘问题 给定一组连续函数 f:Rn→Rm,m⩾n{\mathbf{f}}:{\mathbb{R}^n} \to {\mathbb{R}^m},{\text{ }}m \geqslant nf ...

  9. 朴素贝叶斯算法原理以及python实现

    朴素贝叶斯 一.朴素贝叶斯概述 二.概率论知识 三.朴素贝叶斯算法原理 四.参数估计方法 五.示例分析 六.拉普拉斯平滑修正 七.算法优缺点 八.python实现 8.1 sklearn贝叶斯 8.2 ...

最新文章

  1. puppet yum模块、配置仓储、mount模块
  2. 裴健当选加拿大皇家学会院士:曾任华为首席科学家、京东副总裁,学术引用超8万次...
  3. hash 建表 query 统计重复个数
  4. 转【FullPage.js 应用参数参考与简单调用】
  5. fail-fast与fail-safe工作机制
  6. FFmpeg学习(9)—— 调整播放速度
  7. struts2通配符使用
  8. 最齐全的企业BI建设地图,附高清完整版BI知识图谱
  9. 基于jsp+mysql+Spring+mybatis的SSM健身房管理系统
  10. 北京林业大学matlab公选课,北京林业大学教务处
  11. 分享:Android清除本地数据缓存代码
  12. 桌面虚拟化 VMware Horizon View 7 安装部署指南 云办公系统安装部署
  13. 树莓派1——摄像头实时视频和截图
  14. android 高光动画,InstrumentPanelView
  15. EfficientNet介绍
  16. SpringBoot学习:整合shiro(rememberMe记住我功能)
  17. visual basic_Visual Basic的随机数生成的检验
  18. 联发科发布全新旗舰5G芯片;全球半数雇主计划加薪并恢复至正常招聘水平 | 美通企业日报...
  19. Silverlight的开发工具 1
  20. 你要了解的USB接口知识总结

热门文章

  1. 怎么用计算机直接截图,电脑怎么快速截屏?分享电脑快速截屏的五种方法
  2. 计算机毕业设计(附源码)python游戏盒子系统
  3. 【玩转ESP32】5、i2c-tools访问i2c设备
  4. 计算机组成原理(一):计算机系统体系结构
  5. 软件技术架构演变历史
  6. 如何在winows的PPT里面使用醒目的思源系列字体(思源宋体/黑体)
  7. 21. A1088 Rational Arithmetic
  8. java事务抛异常_java中抛异常后如何使事务回滚
  9. GO学习笔记:struct的匿名字段
  10. python抓取dblp网站的arXiv论文,下载保存成pdf