當(dāng)前位置:
首頁 >
LM算法求解最小二乘问题
發(fā)布時(shí)間:2023/12/10
44
豆豆
生活随笔
收集整理的這篇文章主要介紹了
LM算法求解最小二乘问题
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
Module VarLMImplicit none!//Nparas為參數(shù)個(gè)數(shù),Ndata為數(shù)據(jù)個(gè)數(shù),Niters為最大迭代次數(shù)Integer ,Parameter :: Nparas = 2,Ndata = 9,Niters = 50,Fileid = 11!//臨時(shí)變量,order=1,繼續(xù)迭代,否則停止迭代Integer :: order!//循環(huán)變量,it為迭代次數(shù)循環(huán)變量Integer :: it,i,ii!//x_1為觀測數(shù)據(jù)自變量,y_1為觀測數(shù)據(jù)因變量,兩者均為已知數(shù)據(jù)Real(kind=8),Parameter :: x_1(Ndata) = [0.25,0.5,1.0,1.5,2.0,3.0,4.0,6.0,8.0]Real(kind=8),Parameter :: y_1(Ndata) = [19.306,18.182,16.126,14.302,12.685,9.978,7.849,4.857,3.005] !//a0與b0分別為參數(shù)猜測初始值,RealA、RealB為真值Real(kind=8),Parameter :: a0 = 0.,b0 = 0.,RealA = 20.5,RealB = 0.24!//誤差限度Real(kind=4) :: eps = 1e-8!//y_est為估計(jì)值,d為估計(jì)值和實(shí)際值y_1之間的誤差,rd為數(shù)組d的變形Real(kind=8) :: y_est(Ndata) = 0.,d(Ndata) = 0.,rd(Ndata,1) = 0.!//J為雅可比矩陣,JT為J的轉(zhuǎn)置矩陣,H為海森矩陣Real(kind=8) :: J(Ndata,Nparas) = 0.,JT(Nparas,Ndata) = 0.,H(Nparas,Nparas) = 0.!//Inv_H_1m為H_1m的逆矩陣Real(kind=8) :: H_Lm(Nparas,Nparas)=0.,Inv_H_Lm(Nparas,Nparas)=0.!//eye為單位矩陣,delta為步長矩陣Real(kind=8) :: eye(Nparas,Nparas) = 0.0,delta(Nparas,1) = 0.0!//a_est,b_est分別為反演參數(shù)Real(kind=8) :: a_est = 0.,b_est = 0.,e = 0.!//計(jì)算新對應(yīng)的值Real(kind=8) :: y_est_Lm(Ndata) = 0.,d_Lm(Ndata) = 0.,e_Lm = 0.!//臨時(shí)變量,lamda為LM算法的阻尼系數(shù)初始值Real(kind=8) :: a_Lm,b_Lm,lamda = 0.01,v = 10.d0,tempEnd Module VarLMProgram LMInclude 'link_fnl_shared.h'Use VarLMUse LINRG_INTImplicit None!//生成單位矩陣Forall( i = 1:Nparas, ii = 1:Nparas, i==ii ) eye(i,ii) = 1.d0!//第一步:變量賦值order = 1a_est = a0b_est = b0!//第二步:迭代Write(*,"('------------------------------------------------')") loop1: Do it = 1,NitersIf ( order==1 ) Then !//根據(jù)當(dāng)前估計(jì)值,計(jì)算雅可比矩陣y_est = a_est*Exp( -b_est*x_1 ) !//根據(jù)當(dāng)前a_est,b_est及x_1,得到函數(shù)值y_estd = y_1 - y_est !//計(jì)算已知值y_1與y_est的誤差loop2: Do i = 1,Ndata !//計(jì)算雅可比矩陣。dy/da = Exp(-b*x),dy/db = -a*x*Exp(-b*x)J(i,1) = Exp( -b_est*x_1(i) ) J(i,2) = -a_est*x_1(i)*Exp( -b_est*x_1(i) )End Do loop2 JT=Transpose(J) H = Matmul( JT,J ) !//計(jì)算海森矩陣End IfIf ( it==1 ) e = Dot_Product(d,d) !//若是第一次迭代,計(jì)算誤差epsilonH_Lm = H + lamda*eye !//根據(jù)阻尼系數(shù)lamda混合得到H矩陣!// 縧amda*I縇evenberg靠縧amda*diag(A'A)縈arquardt靠!//計(jì)算步長delta,并根據(jù)步長計(jì)算新的參數(shù)估計(jì)值Call LINRG( H_Lm,Inv_H_Lm ) !//使用imsl函數(shù)庫,計(jì)算H_Lm的逆矩陣Inv_H_Lmrd = Reshape( d,[Ndata,1] ) !//為了滿足內(nèi)部函數(shù)Matmul的計(jì)算法則,對d的數(shù)組形狀進(jìn)行改變delta = Matmul( Inv_H_Lm,matmul( JT,rd ) ) !//delta為增量a_Lm = a_est + delta(1,1)b_Lm = b_est + delta(2,1)!//如果||delta||<1e-8,終止迭代If ( Dot_Product(delta(:,1),delta(:,1))<eps ) Exit!//計(jì)算新的可能估計(jì)值對應(yīng)的y和計(jì)算殘差ey_est_Lm = a_Lm*Exp( -b_Lm*x_1 )d_Lm = y_1 - y_est_Lme_Lm = Dot_Product( d_Lm,d_Lm ) !//e_LM等于||y_1 - y_est_LM||!//根據(jù)誤差,決定如何更新參數(shù)和阻尼系數(shù)!//迭代成功時(shí)將lamda減小,否則增大lamdaIf ( e_Lm<e ) Thenlamda = lamda/va_est = a_Lmb_est = b_Lme = e_Lmorder = 1Elseorder = 0lamda = lamda*vEnd IfWrite(*,"('a_est=',g0,2X,'b_est=',g0)") a_est,b_estEnd Do loop1Write(*,"('------------------------------------------------')") Write(*,"('停止迭代,總共迭代',g0,'次')") it - 1!//輸出正反演數(shù)據(jù)以及百分比誤差輸出到文件,總共100個(gè)數(shù)據(jù)點(diǎn),計(jì)算區(qū)域?yàn)閇0-50]Open(Fileid,file='原始數(shù)據(jù)與反演數(shù)據(jù).dat',status='unknown')Do i = 0,100temp = i/2.d0Write(Fileid,'(f7.3,3f15.8)') temp,RealA*Exp( -RealB*temp ),a_est*Exp( -b_est*temp ),&Abs( a_est*Exp( -b_est*temp )-RealA*Exp( -RealB*temp ) )/RealA/Exp( -RealB*ii )*100End DoClose(Fileid)!//輸出反演參數(shù)a_est,b_est以及原始數(shù)據(jù)和擬合數(shù)據(jù)Write(*,"(/,'反演參數(shù)為:')")Write(*,"('a_est=',g0)") a_estWrite(*,"('b_est=',g0)") b_estWrite(*,"(/,'原始數(shù)據(jù)為:')") Write(*,'(3f9.4/)') y_1Write(*,"('擬合數(shù)據(jù)為:')") Write(*,'(3f9.4/)') a_est*Exp( -b_est*x_1 )Write(*,"('------------------------------------------------')") End Program LM
?
總結(jié)
以上是生活随笔為你收集整理的LM算法求解最小二乘问题的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: E - More is better (
- 下一篇: 预处理指令pragma常见用法集锦(#p