解決のための最小二乗法非線形

 個人ブログ:http://www.chenjianqu.com/

オリジナルリンク:http://www.chenjianqu.com/show-85.html

最小二乗法

    最小二乗法(また、最小二乗法として知られている)は、数学的な最適化技術です。このエラーを最小限に抑え、最高のマッチング機能を見つけるために、データを照合正方形。最小二乗法を使用して容易に未知のデータを計算し、そしてそのような決定されたデータと、これらの実際のデータとの間の最小二乗誤差ということができます。最小二乗曲線フィッティングを使用してもよいです。数学、言いました:

1.JPG

    Yiはi番目の実際の観測値、又は真の値または呼ば目標であり; Fiの(x)は、i番目の値を予測パラメータにより得られるXとみなすことができるが、それはYIの推定値です。最小二乗の目標は、観測値(実際の値)と推定値の差を最小限に抑えるために、未知のパラメータを推定します。

最小二乗線形

    いわゆる線形、F(X)を意味し、X、F(X)= X0 + T1 * X1 + ... + TQ * XQの線形関数です。線形最小二乗解は比較的簡単です。

最小二乗非線形

    線形関係として表現することができない、いわゆる非線形、F(X)が、非直線関係のいくつかの種類。シンプルに考えてみましょう非線形最小二乗問題:

2.JPG

    するf(x)がの種類の機能をフィットは、F(x)は任意のスカラー非線形関数とすることができる目的関数、我々はXを見つけることを願っています(ターゲット関数Fを作る(すなわち、xはパラメータを最適化することがあります) x)の最小値。この問題を解決するには、いくつかの方法があります。

    1. 直接導出、そうはdF / DX = 0が、これは多くの場合、達成することは困難です。

    2. 反復方法

3.JPG

    これは、問題導関数を解決するにはゼロが常に増分衰退Δxkの問題を探しになっていることができます。以下は、増分アプローチを見つけることです。

 

1次および2次勾配法

    最も直接的な方法は、ターゲット関数F(x)はXKの近傍におけるテイラー展開である、Δxk探して、k番目の反復を考えます。

4.JPG

    前記J(XK)は F(X)についてのx、一次導関数である(勾配ヤコビアン(ヤコビ)行列)、H(XK)は、二次(ONであるヘッセ(ヘッセ)行列)。

    上記式のみ一次を保持する場合の用語と呼ばれる方法のステップまたは最急降下法取る、量Δx= -J(XK)、すなわち、方向、逆方向の増分勾配を、通常の工程によって提供さλ。

    あなたは2次の項を残す場合は、この増分式:

5.jpg

    ΔXは、右に対して誘導体を見つけて0にするために、与える:J +HΔx= 0、すなわち  HΔx= -J&LTを 線形方程式を解くと、メソッドが呼び出され、増分得られる二次勾配法ニュートン法

    簡単にギザギザの線のうち、あまりにも貪欲法の梯子が、反復回数を増加させ、そして二次勾配ルールが問題のより大きなスケールでは非常に困難である目的関数のH行列を計算する必要がある、我々は、通常、Hの計算を回避する傾向があります

 

ガウス・ニュートン法

    関数に合わせてF(X-) ない目的関数F(x)は、それ以外の場合はニュートン法になります)一次テイラー展開を:

6.jpg

    J(x)はf(x)がある場合NX1列ベクトルとして、xに関する導関数です。私たちの目標は、そのように、増分Δxだけを見つけることであるF(X +Δxだけ)| | 2 最小。Δxだけを追求するためには、線形最小二乗問題の解決が必要です。

7.jpg

    目的関数のΔxの上記誘導体、及びゼロに等しい誘導体を作ります。この目的を達成するために、目的関数における二乗項の最初の拡張:

8.jpg

    、△X、その後誘導体が、それが0であること、与えること:J(X)F(X)+ J(X)JT(X)δX = 0、すなわち:

J(x)は、JT(X)のΔx= -  J(x)は、F(X) 

    式は、変数の線形方程式であるΔX、と呼ばれる増分式、またはいわゆるガウス・ニュートン方程式(ガウス-ニュートン方程式)または正規方程式(正規方程式)。そうH = J(X)JT(X)、G = -J&LT(X)F(X)は、ガウス-ニュートン方程式は次のようになります。

    HΔx=グラム

    比較におけるニュートン法HΔx= -J&LT、Gauss-Newton法、それによってHの計算を省略し、ニュートン近似法、ヘッセ行列としてJ(x)は、JT(X)を使用し 方程式ガウス・ニュートンの最適化を解決することが、我々はこの方程式を解くことができれば、次のように、Gauss-Newton法の段階であるが、全体の問題の核心であります:

10.jpg

    式増分を解決するために、H-1、H-マトリックス可逆必要を解く必要があります。しかし、実際には半分だけ明確H、Hが特異行列の場合、または悪い状態であってもよいである、乏しい安定性の増加、その場合、アルゴリズムを得られたことは収束しません。でも、H正則でも病気がありますが、ステップのΔxのあまり外に言わせれば、私たちは反復収束を保証することはできません。

 

レーベンバーグ - マルカート法

    この方法の収束速度も呼ばれるガウス・ニュートン法、より遅いニュートン法を減衰します呼ばれる範囲、追加するΔxを考えるのが自然であるように、テイラー展開の2次近似で使用されるガウス・ニュートン法は、より良いおおよその効果ポイントの近くに配置することができ信頼領域(信託リージョン)この範囲は、二次の近似が有効な、そのような方法も呼ばれれる状況定義信頼領域法(方法、信頼領域)信頼の内側の領域では、我々は近似が有効であることを信じている。アウトこの地域の、同様の問題が発生することがあります。

    それでは、どのように地域の信頼、それの範囲を決定するのですか?より良いアプローチは、実際の関数との近似モデルとの差に基づいて決定されるべきである:差が小さい場合には、優れた近似の効果を示し、我々は近似の範囲を拡大している。差が大きい場合は逆に、おおよその範囲を狭めます。我々は、次の式で近似する方法も特徴づけるためのメトリックρが6.34である定義します。

11.jpg

    ρは、分母が近似モデルを落下値であり、分子下降値の実際の関数です。ρが1に近い場合、それは良い近似です。ρは、はるかに少ない約減少の減少値の実際の値以上を示し、小さすぎると、それは比較的貧弱な近似であると考えられる、近似は狭い範囲を必要とします。ρが比較的大きい場合は逆に、実際の下落が予想以上に、我々はおおよその範囲にズームすることができます。次のようにこのように新しい手順は次のとおりです。

100.jpg   

    ここでは、複数の拡張としきい値のμおおよその範囲は、経験的な値です。式(6.35)において、増加は、この球が有効であるだけで、半径μの球体を定義します。ベルトDの後、ボールは楕円と見なすことができます。レーベンバーグによって提案された最適化方法では、取り込まD ユニットは、IをマトリックスボールΔxk制約に直接対応します。Dマーコートは取ることが提案非負対角行列、対角要素の平方根の通常JTJの練習ように小さな大きな寸法の範囲内の勾配の制約- 。

    我々はラグランジュ関数を構成し、目的関数にラグランジュ乗数項の制約を使用し、勾配は式(6.35)を解くために必要な取得し、この問題は不等式制約を持つサブ最適化問題です:

14.jpg

    λ为拉格朗日乘子。类似于高斯牛顿法中的做法,令该拉格朗日函数关于 ∆x 的导数为零,它的核心仍是计算增量的线性方程:(H + λDTD) ∆xk = g 。这里的增量方程相比于高斯牛顿法多了一项λDTD,若 D=I,则求解的是:

     (H + λI) ∆xk = g

    当参数 λ 比较小时,H 占主要地位,这说明二次近似模型在该范围内是比较好的,列文伯格—马夸尔特方法更接近于高斯牛顿法。当 λ 比较大时,λI 占据主要地位,列文伯格—马夸尔特方法更接近于一阶梯度下降法(即最速下降),这说明附近的二次近似不够好。

    列文伯格—马夸尔特方法的求解方式,可在一定程度上避免线性方程组的系数矩阵的非奇异和病态问题,提供更稳定、更准确的增量 ∆x。在实际中,还存在许多其他的方式来求解增量,例如 Dog-Leg 等方法。

 

曲线拟合

    要拟合的曲线:y = exp(ax2 + bx + c) + w,其中a、b、c为曲线参数,w为0均值、σ标准差的高斯噪声。假设有N个观测点,则使用高斯牛顿法求解下面的最小二乘问题以估计曲线参数:

15.jpg

    定义误差为:ei = yi - exp(axi2 + bxi + c),这里的状态变量为a,b,c,求出每个误差项对于状态变量的导数:

17.jpg

    于是雅可比矩阵为:

18.jpg

    得高斯牛顿方程:

19.jpg

    代码如下:

CMakeLists.txt

cmake_minimum_required(VERSION 2.6)
project(gaussnewtontest)
# 添加c++ 11标准支持
set( CMAKE_CXX_FLAGS "-std=c++11" )
include_directories("/usr/include/eigen3")
find_package( OpenCV REQUIRED )
include_directories( ${OpenCV_INCLUDE_DIRS} )
add_executable(gaussnewtontest main.cpp)
target_link_libraries(gaussnewtontest ${OpenCV_LIBS} )
install(TARGETS gaussnewtontest RUNTIME DESTINATION bin)

main.cpp

#include <iostream>
#include <opencv2/opencv.hpp>
#include <Eigen/Core>
#include <Eigen/Dense>

using namespace std;
using namespace Eigen;

int main(int argc, char **argv) {
  double ar = 1.0, br = 2.0, cr = 1.0;         // 真实参数值
  double ae = 2.0, be = -1.0, ce = 5.0;        // 估计参数值
  int N = 100;                                 // 数据点
  double w_sigma = 1.0;                        // 噪声Sigma值
  double inv_sigma = 1.0 / w_sigma;
  cv::RNG rng;   
                                // OpenCV随机数产生器
  vector<double> x_data, y_data;      // 数据
  for (int i = 0; i < N; i++) {
    double x = i / 100.0;
    x_data.push_back(x);
    y_data.push_back(exp(ar * x * x + br * x + cr) + rng.gaussian(w_sigma * w_sigma));
  }
  
  // 开始Gauss-Newton迭代
  int iterations = 100;    // 迭代次数
  double cost = 0, lastCost = 0;  // 本次迭代的cost和上一次迭代的cost
  
  for (int iter = 0; iter < iterations; iter++) {
    Matrix3d H = Matrix3d::Zero();             // Hessian = J^T W^{-1} J in Gauss-Newton
    Vector3d b = Vector3d::Zero();             // bias
    cost = 0;
    for (int i = 0; i < N; i++) {
      double xi = x_data[i], yi = y_data[i];  // 第i个数据点
      double error = yi - exp(ae * xi * xi + be * xi + ce);
      Vector3d J; // 雅可比矩阵
      J[0] = -xi * xi * exp(ae * xi * xi + be * xi + ce);  // de/da
      J[1] = -xi * exp(ae * xi * xi + be * xi + ce);  // de/db
      J[2] = -exp(ae * xi * xi + be * xi + ce);  // de/dc
      H += inv_sigma * inv_sigma * J * J.transpose();
      b += -inv_sigma * inv_sigma * error * J;
      cost += error * error;
    }
    
    // 求解线性方程 Hx=b
    Vector3d dx = H.ldlt().solve(b);
    if (isnan(dx[0])) {
      cout << "result is nan!" << endl;
      break;
    }
    
    if (iter > 0 && cost >= lastCost) {
      cout << "cost: " << cost << ">= last cost: " << lastCost << ", break." << endl;
      break;
    }
    
    ae += dx[0];
    be += dx[1];
    ce += dx[2];
    lastCost =コスト; 
    裁判所未満<< "総費用:" <<コスト<< "\トン\ tupdate: "<< dx.transpose()<< 
         "\トン\ testimatedのparams:" << AE <<"、" <<こと< < "" << CE <<てendl; 
  } 
  
  
  COUT << "推定ABC =" << AE << " "<< <<である"、" << CE << ENDL。
  0を返します。
}

 

 

リファレンス

[1]コビジョンSLAM14話

最小二乗非線形最小二乗法線形[2]江ファイ。Https://www.jianshu.com/p/bf6ec56e26bd 

 

公開された74元の記事 ウォン称賛33 ビュー10000 +

おすすめ

転載: blog.csdn.net/qq_37394634/article/details/104430491