LM算法初识
??由于工作內容接觸到點云標定,需要用到最小二乘法,所以特意花了點時間研究LM算法,但是由于大學的高等數學忘得差不多了,所以本文從最基本的一些數學概念開始;
信賴域法
??在最優化算法中,都是要求一個函數的極小值,每一步迭代中,都要求目標函數值是下降的,而信賴域法,顧名思義,就是從初始點開始,先假設一個可以信賴的最大位移,然后在以當前點為中心,以為半徑的區域內,通過尋找目標函數的一個近似函數(二次的)的最優點,來求解得到真正的位移。在得到了位移之后,再計算目標函數值,如果其使目標函數值的下降滿足了一定條件,那么就說明這個位移是可靠的,則繼續按此規則迭代計算下去;如果其不能使目標函數值的下降滿足一定的條件,則應減小信賴域的范圍,再重新求解。
泰勒公式:
雅可比矩陣
??雅可比矩陣幾乎在所有的最優化算法中都有提及,因此我們很有必要了解一下其具到底是什么,關于這一點,下方截圖說的很清楚;
??從上面可以了解,雅可比矩陣實際上就是一階偏導數所組成的矩陣,其列數由未知參數個數決定,其行數由我們提供的輸入參數組決定;
各種最優化算法
??需要注意的是,對于LM算法,可以具體到下種形式:
??其中,r是殘差;
代碼實現
??LM算法的關鍵是用模型函數 f 對待估參數向量p在其領域內做線性近似,忽略掉二階以上的導數項,從而轉化為線性最小二乘問題,它具有收斂速度快等優點。
??LM算法需要對每一個待估參數求偏導,所以,如果你的擬合函數 f 非常復雜,或者待估參數相當地多,那么就不適合使用LM算法了,可以使用Powell算法,Powell算法不需要求導。
??需要說明的是,這是非線性無約束的問題,如果待估參數是有約束的,暫時還沒有涉及到這個領域;
??就是從初始點開始,先假設一個可以信賴的最大位移,然后在以當前點為中心,以為半徑的區域內,通過尋找目標函數的一個近似函數(二次的)的最優點,來求解得到真正的位移。在得到了位移之后,再計算目標函數值,如果其使目標函數值的下降滿足了一定條件,那么就說明這個位移是可靠的,則繼續按此規則迭代計算下去;如果其不能使目標函數值的下降滿足一定的條件,則應減小信賴域的范圍,再重新求解。
??在使用Levenberg-Marquart時,先設置一個比較小的μ值,當發現目標函數反而增大時,將μ增大使用梯度下降法快速尋找,然后再將μ減小使用牛頓法進行尋找。
6.阻尼系數的調整
??當阻尼系數足夠大時,使算法更接近最速下降法,所以在殘差沒有明顯變化時可以使用;當阻尼系數足夠小時,算法更接近高斯牛頓算法,此時迭代速度更快;
??有算法精度ep和上一次殘差e,當e<lamda < ep時,lamda = lamda/5,當lamda > ep時,lamda = lamda*5,當lamda < ep時,lamda = lamda;
??代碼如下:
% 計算函數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_itersif 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==1e=dot(d,d); % 可以認為e是初始值計算所估誤差endend% 根據阻尼系數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和計算殘差ey_est_lm = a_lm*cos(b_lm*data_1) + b_lm*sin(a_lm*data_1);d_lm=obs_1-y_est_lme_lm=dot(d_lm,d_lm) % 這個值后面主要用于和上一次誤差進行比對,從而調整阻尼系數% 根據誤差,決定如何更新參數和阻尼系數if e_lm<e % 如果小于上一次誤差if e_lm<ep % 如果小于算法精度break % 結束,說明該阻尼系數合理elselamda=lamda/5; % 如果小于上一次誤差,但大于算法精度,那么更新阻尼系數,同時將當前評估參數作為初始值重新計算a_est=a_lm;b_est=b_lm;e=e_lm;disp(e);updateJ=1; endelseupdateJ=0;lamda=lamda*5;endend %顯示優化的結果 a_est b_estplot(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')參考鏈接:
https://blog.csdn.net/a6333230/article/details/83304098
https://blog.csdn.net/baidu_38172402/article/details/82223284
https://zhuanlan.zhihu.com/p/39762178
http://www.360doc.com/content/18/0330/13/18306241_741511614.shtml
https://blog.csdn.net/xueyinhualuo/article/details/46931989?utm_medium=distribute.pc_relevant.none-task-blog-
https://www.cnblogs.com/shhu1993/p/4878992.html
https://en.wikipedia.org/wiki/Levenberg%E2%80%93Marquardt_algorithm
總結
- 上一篇: C#浮点数据类型
- 下一篇: jQuery基本语法