Levenberg-Marquardt算法的局限性

Mar*_*cin 3 math optimization nonlinear-functions levenberg-marquardt

我使用Levenberg-Marquardt算法来最小化6个参数的非线性函数.每次最小化我有大约50个数据点,但是我得不到足够准确的结果.我的参数相差几个数量级的事实是否非常重要?如果是,我应该在哪里寻找解决方案?如果不是,您在工作中遇到的LMA有哪些限制(可能有助于找到我的应用中的其他问题)?非常感谢您的帮助.

编辑:我想解决的问题是确定最佳转换T:

typedef struct 
{
    double x_translation, y_translation, z_translation; 
    double x_rotation, y_rotation, z_rotation;
} transform_3D;
Run Code Online (Sandbox Code Playgroud)

使3D点集合适合3D线条.详细地说,我有一组3D点的坐标和相应3D线的方程,这些坐标应该通过这些点(在理想情况下).LMA正在最小化变换的3D点到相应的3D线的距离的总和.变换函数如下:

cv::Point3d Geometry::transformation_3D(cv::Point3d point, transform_3D transformation)
{
    cv::Point3d p_odd,p_even;

    //rotation x
    p_odd.x=point.x;
    p_odd.y=point.y*cos(transformation.x_rotation)-point.z*sin(transformation.x_rotation); 
    p_odd.z=point.y*sin(transformation.x_rotation)+point.z*cos(transformation.x_rotation);

    //rotation y
    p_even.x=p_odd.z*sin(transformation.y_rotation)+p_odd.x*cos(transformation.y_rotation);
    p_even.y=p_odd.y;
    p_even.z=p_odd.z*cos(transformation.y_rotation)-p_odd.x*sin(transformation.y_rotation);

    //rotation z
    p_odd.x=p_even.x*cos(transformation.z_rotation)-p_even.y*sin(transformation.z_rotation);
    p_odd.y=p_even.x*sin(transformation.z_rotation)+p_even.y*cos(transformation.z_rotation);
    p_odd.z=p_even.z;

    //translation
    p_even.x=p_odd.x+transformation.x_translation;
    p_even.y=p_odd.y+transformation.y_translation;
    p_even.z=p_odd.z+transformation.z_translation;

    return p_even;
}
Run Code Online (Sandbox Code Playgroud)

希望这个解释会有所帮助......

EDIT2:

一些示例性数据粘贴在下面.3D线由中心点和方向矢量描述.所有线的中心点都是(0,0,0),每个矢量的'uz'坐标等于1.方向矢量的'ux'坐标集:

-1.0986, -1.0986, -1.0986,
-1.0986, -1.0990, -1.0986,
-1.0986, -1.0986, -0.9995,
-0.9996, -0.9996, -0.9995,
-0.9995, -0.9995, -0.9996,
-0.9003, -0.9003, -0.9004,
-0.9003, -0.9003, -0.9003,
-0.9003, -0.9003, -0.8011,
-0.7020, -0.7019, -0.6028,
-0.5035, -0.5037, -0.4045,
-0.3052, -0.3053, -0.2062,
-0.1069, -0.1069, -0.1075,
-0.1070, -0.1070, -0.1069,
-0.1069, -0.1070, -0.0079,
-0.0079, -0.0079, -0.0078,
-0.0078, -0.0079, -0.0079,
 0.0914,  0.0914,  0.0913,
 0.0913,  0.0914,  0.0915,
 0.0914,  0.0914
Run Code Online (Sandbox Code Playgroud)

定向向量的'uy'坐标集:

-0.2032,  -0.0047,    0.1936,
0.3919,    0.5901,    0.7885,
0.9869,    1.1852,    -0.1040,
0.0944,    0.2927,    0.4911,
0.6894,    0.8877,    1.0860,
-0.2032,  -0.0047,    0.1936,
0.3919,    0.5902,    0.7885,
0.9869,    1.1852,    1.0860,
0.9869,    1.1852,    1.0861,
0.9865,    1.1853,    1.0860,
0.9870,    1.1852,    1.0861,
-0.2032,  -0.0047,    0.1937,
0.3919,    0.5902,    0.7885,
0.9869,    1.1852,    -0.1039,
0.0944,    0.2927,    0.4911,
0.6894,    0.8877,    1.0860,
-0.2032,  -0.0047,    0.1935,
0.3919,    0.5902,    0.7885,
0.9869,    1.1852
Run Code Online (Sandbox Code Playgroud)

和(xyzxyzxyz ...)形式的3D点集:

 {{0, 0, 0}, {0, 16, 0},   {0, 32, 0}, 
 {0, 48, 0}, {0, 64, 0},   {0, 80, 0},
 {0, 96, 0}, {0, 112,0},   {8, 8, 0},
 {8, 24, 0}, {8, 40, 0},   {8, 56, 0}, 
 {8, 72, 0}, {8, 88, 0},   {8, 104, 0}, 
 {16, 0, 0}, {16, 16,0},   {16, 32, 0}, 
{16, 48, 0}, {16, 64, 0},  {16, 80, 0}, 
{16, 96, 0}, {16, 112, 0}, {24, 104, 0}, 
{32, 96, 0}, {32, 112, 0}, {40, 104, 0},
{48, 96, 0}, {48, 112, 0}, {56, 104, 0},
{64, 96, 0}, {64, 112, 0}, {72, 104, 0}, 
{80, 0, 0},  {80, 16, 0},  {80, 32, 0},
{80,48, 0},  {80, 64, 0},  {80, 80, 0}, 
{80, 96, 0}, {80, 112, 0}, {88,  8, 0}, 
{88, 24, 0}, {88, 40, 0},  {88, 56, 0},
{88, 72, 0}, {88, 88, 0},  {88, 104, 0},
{96, 0, 0},  {96, 16, 0},  {96, 32, 0}, 
{96, 48,0},  {96, 64, 0},  {96, 80, 0}, 
{96, 96, 0}, {96, 112, 0}} 
Run Code Online (Sandbox Code Playgroud)

这是一种具有非常小旋转的"简单"建模数据.

小智 5

那么,使用Levenberg-Marquardt的正确方法是你需要对参数进行良好的初始估计("种子").回想一下LM是Newton-Raphson的变种; 与这样的迭代算法一样,起点的质量将决定你的迭代; 要么收敛到你想要什么,汇聚成完全不同的东西(不是不可能发生的,特别是如果你有很多的参数),或者拍摄过到野外的蓝色天空(发散).

无论如何,如果您能够提到您正在拟合的模型函数,并且可能是您的数据的散点图,那将会更有帮助; 它可能会为寻找可行的解决方案走很长的路.