着手查出牛顿法不稳定的原因

今天把测试Hessian的代码加进去了,但是发现Hessian并无大的问题。

测试例子:一根圆柱向指定方向弯曲。

下面对比,在有弯曲方向参数,与无方向参数(该参数被被乘以0)的情况下,各帧迭代的函数值。

无方向参数:

帧号 1 2 3 4 5
第1次迭代 0 73777.396480 615269.331763 1566548.018724 2799725.912609
第2次迭代   150.018686 1116.876970 3499.198322 8757.705770
第3次迭代   144.756549 785.078791 1510.680152 2220.662691
第4次迭代     785.053385 1510.524488 2219.948136

 

 

 

 

有方向参数

帧号 1 2 3 4 5
第1次迭代 0 73777.396480 615457.873791 1566753.791283 2797987.408846
第2次迭代   238.365110 1093.703963 2470.166542 6643.182270
第3次迭代   234.873881 837.922487 693.717725 561.082432
第4次迭代   234.873881 837.922027 693.695513 560.826661

 

 

 

 

 

关键在于第二帧,两种方法的初始函数值是相同的,但是最终却收敛到不同的值。而且有方向的参数收敛到的值要大一些。猜测是收敛到局部极值点了。为了验证这一点,需要检查第二帧两种方法的梯度。

 

  1 2 3 4
无方向梯度Gn 1437015.459672 12004.873928 9.966298  
有方向梯度Gn 1437015.459672 10015.666457 1.390628 0.000000
无方向梯度Gp 5596204.567079 2756.358209 0.697293  
有方向梯度Gp 5596204.567079 10439.419591 464.339724 0.271374

 

 

 

 

 

两个梯度都收敛,但估计收敛的方向不同。

 

若改变导数有限差商的步长,不影响收敛趋势,只是具体每步迭代的梯度值会稍微变化。

在计算导数的过程中,q,v,a,p的值都没有被错误修改。因此迭代的过程是确实收敛的。

 

写一个测试导数的命令。

用无方向的方法模拟一次,测试第二帧最终梯度:

funVal:144.757682 gradient: |gn| = 5.132273, |gp| = 1.245470

测试梯度是否为函数线性近似:
// step = 1.000000e+002 funVal = 1.525598e+014 approxVal = -2.973997e+002 error = 1.525598e+014 error/dx^2 = 1.525598e+010 //
// step = 1.000000e+001 funVal = 1.498637e+012 approxVal = 1.005419e+002 error = 1.498637e+012 error/dx^2 = 1.498637e+010 //
// step = 1.000000e+000 funVal = 1.244686e+010 approxVal = 1.403361e+002 error = 1.244686e+010 error/dx^2 = 1.244686e+010 //
// step = 1.000000e-001 funVal = 6.226740e+007 approxVal = 1.443155e+002 error = 6.226725e+007 error/dx^2 = 6.226725e+009 //
// step = 1.000000e-002 funVal = 6.349599e+005 approxVal = 1.447135e+002 error = 6.348152e+005 error/dx^2 = 6.348152e+009 //
// step = 1.000000e-003 funVal = 6.504549e+003 approxVal = 1.447533e+002 error = 6.359796e+003 error/dx^2 = 6.359796e+009 //
// step = 1.000000e-004 funVal = 2.083666e+002 approxVal = 1.447572e+002 error = 6.360932e+001 error/dx^2 = 6.360932e+009 //

此时把系统改为有方向,测试此时梯度:

funVal2:144.757682 gradient2: |gn| = 5.132273, |gp| = 1.285636

测试梯度是否为函数线性近似:

// step = 1.000000e+002 funVal = 1.412399e+014 approxVal = 2.651699e+002 error = 1.412399e+014 error/dx^2 = 1.412399e+010 //
// step = 1.000000e+001 funVal = 1.386940e+012 approxVal = 1.567989e+002 error = 1.386940e+012 error/dx^2 = 1.386940e+010 //
// step = 1.000000e+000 funVal = 1.000263e+010 approxVal = 1.459618e+002 error = 1.000263e+010 error/dx^2 = 1.000263e+010 //
// step = 1.000000e-001 funVal = 5.004513e+007 approxVal = 1.448781e+002 error = 5.004499e+007 error/dx^2 = 5.004499e+009 //
// step = 1.000000e-002 funVal = 4.971193e+005 approxVal = 1.447697e+002 error = 4.969745e+005 error/dx^2 = 4.969745e+009 //
// step = 1.000000e-003 funVal = 5.112932e+003 approxVal = 1.447589e+002 error = 4.968173e+003 error/dx^2 = 4.968173e+009 //
// step = 1.000000e-004 funVal = 1.944345e+002 approxVal = 1.447578e+002 error = 4.967674e+001 error/dx^2 = 4.967674e+009 //
// step = 1.000000e-005 funVal = 1.452514e+002 approxVal = 1.447577e+002 error = 4.937210e-001 error/dx^2 = 4.937210e+009 //

 

可见此时结果比较接近。现在怀疑有方向和无方向这两种情况,在迭代的后期对函数值仅有微小的影响,在迭代的后期,步长的前进极为缓慢,因而导致不同的结果。

 

进一步提高迭代精度发现,在迭代的后期,梯度值可以变得很小。这暗示函数是收敛到局部最小值了。

posted @ 2015-01-14 12:28  dydx  阅读(362)  评论(0编辑  收藏  举报