Matlab:优化器/求解器的准确性差

时间:2013-02-21 13:55:30

标签: matlab mathematical-optimization solver equation-solving optimization

我很难在Matlab上找到根发现问题的准确性。我有一个函数Lik(k),并希望找到k Lik(k)=L0的值。基本上,问题是各种内置的Matlab求解器(fzerofminbndfmincon)没有像我希望的那样接近解决方案。

Lik()是一个用户定义的函数,它涉及大量编码以计算数值逆拉普拉斯变换等,因此我不包括完整代码。但是,我已广泛使用此功能,它似乎正常工作。 Lik()实际上需要多个输入参数,但对于当前步骤,除了k之外,所有这些参数都是固定的。所以它确实是一个根本寻找问题。

我想找到k >= 165.95的{​​{1}}的值。 Lik(k)-L0 = 0小于Lik(165.95),我希望L0从此处单调增加。事实上,我可以在感兴趣的范围内评估Lik(k),它似乎平滑地过零:例如Lik(k)-L0。所以看起来这个功能表现得很好。

但是,我试图通过几种不同的方法“自动”找到根,并且准确性不如我预期的那么好......

使用Lik(165.95)-L0 = -0.7465, ..., Lik(170.5)-L0 = -0.1594, Lik(171)-L0 = -0.0344, Lik(171.5)-L0 = 0.1015, ... Lik(173)-L0 = 0.5730, ..., Lik(200)-L0 = 19.80:如果约束到fzero(@(k) Lik(k)-L0)区间,(165.95,173)会返回fzero k=170.96。好的,虽然不是很好。而且出于实际目的,如果没有大量的手工试错,我就不会知道这样一个精确的上限。如果我使用区间Lik(k)-L0=-0.045(165.95,200)会返回fzero k=167.19,而Lik(k)-L0 = -0.65则相当差。我一直在运行这些测试,并将显示设置为 iter ,这样我就可以看到正在发生的事情,并且fzero点击了167.19第4次迭代然后在第5次迭代中保持不变,这意味着k从一次迭代到下一次迭代的变化小于TolX(设置为0.001),因此过程结束。退出标志表示它已成功收敛到解决方案。

我还尝试使用abs(Lik(k)-L0) {给出fminbnd的上限和下限)和k(给出fmincon的起点)来最小化k和遇到了类似的准确性问题。特别是,使用fmincon可以同时设置TolXTolFun,但玩这些(低至10 ^ -6,比我需要的精度高得多)没有任何区别。令人困惑的是,有时优化器甚至会在较早的迭代中找到一个k值,该值更接近于使目标函数为零而不是它返回的最终k值。

因此,似乎算法迭代到某个点,然后没有采取足够大小的任何进一步步骤来找到更好的解决方案。有谁知道为什么算法不采取另一个更大的步骤?有什么我可以调整来改变这个吗? (我查看了 optimset 下的列表,但没有提供任何有用的信息。)

非常感谢!

3 个答案:

答案 0 :(得分:1)

由于你似乎有一个'野性'功能,在该地区看似单调,相当小的兴趣范围,而不是对精度的要求非常高我认为所有标准都符合推荐蛮力方法。

假设在一个点上评估函数不需要太多时间,请尝试:

找到上限xmax和下限xmin,选择首选stepsize并评估您的功能

xmin:stepsize:xmax 

如果需要(并且单调性确实适用),您可以通过这样做获得另一个上限和下限,并重复该过程以获得更好的准确性。

答案 1 :(得分:1)

使用fmincon时我也遇到过这个问题。以下是我修复它的方法。

我需要在优化循环(多个变量)中找到函数(单变量)的解。因此,我需要为单变量函数的解决方案提供一个大的间隔。问题是如果搜索间隔太大,fmincon(或fzero)不会收敛到解决方案。为了解决这个问题,我解决了while循环中的问题,使用了一个巨大的起始上限(1e200),并对求解器产生的fval值进行了约束。如果得到的fval不够小,我会将上限减少一个因子。代码看起来像这样:

fval = 1;
factor = 1;
while fval>1e-7
    UB = factor*1e200;
    [x,fval,exitflag] = fminbnd(@(x)function(x,...),LB,UB,options);
    factor = factor * 0.001;
end

当找到一个好的解决方案时,求解器会退出。你当然可以通过引入另一个因子和/或增加因子步骤来玩LB。 我的第一语言不是英语,所以我为任何错误道歉。

干杯, 克里斯蒂安

答案 2 :(得分:0)

为什么不使用简单的二分法?您总是评估某个间隔的中间值,然后将其减少到右侧或左侧部分,这样您总是有一个边界给出一个负值而另一个边界给出一个正值。您可以非常快速地降低到任意精度。由于每次将间隔减少一半,它应该很快收敛。

我怀疑该函数存在其他问题,因为它具有不连续性。 fzero工作得如此糟糕似乎很奇怪。这是一个确定性的功能吧?