【原】手寫梯度下降《三》之 - 一階法(最速下降法)


前言:最速下降法,在SLAM中,作為一種很重要求解位姿最優值的方法,缺點很明顯:迭代次數太多,盡管Newton法(保留目標函數的二階項Hessian矩陣)改善了“迭代次數過多”這一缺點,但是Hessian矩陣規模龐大(參考:特征匹配點成百對),計算較為困難。Gaussian-Newton法在Newton原有基礎上,用的是一階雅克比的轉置*一階雅克比 JTJ 來近似 Hessian, 但是,這里的近似替換 JTJ並不一定正定。一般,主流非線性優化方法:Levenberg-Marquadt、Dog-leg較為常用,這里不作介紹。

 

一、梯度下降相關數學概念

 

個人理解:是方向偏導數,我們不僅要使得梯度下降,還要以最快的步伐下降。

 

有關負梯度下降為什么是最快的?另一種理解,請參考:https://zhuanlan.zhihu.com/p/24913912

 

 

x* 是無約束問題的局部最優解 =》 x*是其目標函數的駐點

(回想起SVM當中求解有約束目標函數最優值,利用拉格朗日乘子法進行轉換。)

例如:在 y = x^3的曲線當中,x = 0處是 極大值點,也不是極小值點,稱作:鞍點。

 

 

理解定理3:我們翻開書,看到如下概念:

性質

(1)如果一個函數f(x)在某個區間I上有f''(x)(即二階導數)>0恆成立,那么對於區間I上的任意x,y,總有:

f(x)+f(y)≥2f[(x+y)/2],如果總有f''(x)<0成立,那么上式的不等號反向。 

幾何的直觀解釋:如果一個函數f(x)在某個區間I上有f''(x)(即二階導數)>0恆成立,那么在區間I上f(x)的圖象上的任意兩點連出的一條線段,這兩點之間的函數圖象都在該線段的下方,反之在該線段的上方。

(2)判斷函數極大值以及極小值。

結合一階、二階導數可以求函數的極值。當一階導數等於0,而二階導數大於0時,為極小值點。當一階導數等於0,而二階導數小於0時,為極大值點;當一階導數和二階導數都等於0時,為駐點。

(3)函數凹凸性。

設f(x)在[a,b]上連續,在(a,b)內具有一階和二階導數,那么,

(1)若在(a,b)內f''(x)>0,則f(x)在[a,b]上的圖形是的;

(2)若在(a,b)內f’‘(x)<0,則f(x)在[a,b]上的圖形是的。

 

 

 

凸優化,參考:https://blog.csdn.net/kebu12345678/article/details/54926287

 

 

 二、例題講解

 

 

 參考:https://blog.csdn.net/wangdingqiaoit/article/details/23454769

准備相關腳本函數:

 1 function [ y ] = GDMin2(fx,var,x,e,MAX)
 2 % 最速梯度下降法求解函數極小點
 3 % 參數描述------------------------------
 4 %   fx  符號表達式 如fx = (x1-2)^4+(x1-2*x2)^2 5 %   var 符號變量列表 如:syms x1 x2;var= [x1;x2];
 6 %   x  起始位置
 7 %   e 精度控制
 8 %   MAX 最大迭代次數控制
 9 % ------------------------------
10 
11 if nargin < 5
12     MAX = 10;%設置默認最大迭代次數
13 end
14 precision = 3;%顯示精度控制
15 
16 %開始循環迭代
17 %direction存貯搜索方向
18 %step 存貯步長
19 
20 bfound = 0;
21 for k=1:1:MAX
22     direction = getNextDirecrion(fx,var,x);
23     disp('------------------------------');
24     fprintf('d[%d]=:',k);
25     disp( vpa(direction',precision) );
26     if normest(direction) <= e
27         y = x;
28         bfound = 1;%得到結果時置為1
29         break;
30     else
31         step = getNextStep(fx,var, x,direction);%計算步長
32         if isempty(step) 
33             error('can not find a proper step.');
34         end
35         %打印求解過程
36         fprintf('X[%d]=:',k);
37         disp( vpa(x',precision) );
38         fprintf('step(%d)=: ', k);
39         disp( vpa(step,precision) );
40         disp('------------------------------');
41         x = x+step*direction;%計算下一個位置
42     end
43 end
44 if bfound == 1 
45     disp('min value of:');
46     disp( vpa( subs(fx,var,y),precision) );
47 end
48 end
49 
50 %根據位置xk,獲取搜索方向
51 function [direction] = getNextDirecrion(fx,var,xk)
52 
53     gx = gradient(fx,var); %計算梯度函數
54     direction = -subs(gx,var,xk);%計算搜索方向
55 end
56 
57 %根據位置xk和方向dk,獲取搜索步長step
58 %注意符號表達式求導數的根時返回值轉換為double類型
59 function [step] =getNextStep(fx,var,xk,dk) 
60 
61     syms lambda;
62     phix = subs(fx,var,xk+lambda*dk);
63     phix_diff = diff(phix);
64     step = double(solve(phix_diff,'Real',true));%求取導函數的實數根
65 end

在MATLAB命令行鍵入:

1 clear all;
2 syms x1 x2;
3 X = [x1;x2];
4 fx = x1 - x2 + 2*x1^2 + 2*x1*x2 + x2^2;
5 x1 = [0;0];
6 e = 0.3;
7 minVal = GDMin2(fx,X,x1,e)

結果:

------------------------------
d[1]=:[ -1.0, 1.0]

X[1]=:[ 0, 0]

step(1)=: 1.0

------------------------------
------------------------------
d[2]=:[ 1.0, 1.0]

X[2]=:[ -1.0, 1.0]

step(2)=: 0.2

------------------------------
------------------------------
d[3]=:[ -0.2, 0.2]

min value of:
-1.2


minVal =

-4/5
6/5

 

 和手動結算的結果是一樣的在 x 取值 [-0.8,  1.2]的時候,取得滿足精度的值。

 

 我們看前兩步:

畫出其迭代路線:

 1 clear all;
 2 clc;
 3 close all;
 4 x = 0:0.1:8
 5 fx = (x(1,:) - 4).^2
 6 
 7 
 8 plot(x, fx);
 9 hold on
10 
11 %% 標出點
12 plot(3, 1, '-ro');
13 plot(4, 0, '-ro');
14 hold on
15 
16 %% 連線
17 %% plot([x1,x2...], [y1,y2,...])
18 plot([3 4],[1 0], '-g'); 
19 hold off 

 

兩步就收斂;

現在,如果我們將初始值(startpoints)改為:x = 2;再根據上述求解過程,畫出迭代路線:

可以看到,起始點是 x  = 2 比 x = 3的迭代次數多一次,所以選取一個好的初始值十分重要;同樣,在SLAM當中,例如:3D-3D映射;我們在RANSAC框架下,基於PNP/ICP 計算出位姿初始值,這樣一個初始值,在后續BA當中,是一個較為理想的初始值。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM