0

我很难在 Matlab 上的求根问题中达到足够的准确性。我有一个函数 ,Lik(k)并且想找到kwhere的值Lik(k)=L0。基本上,问题在于各种内置的 Matlab 求解器 ( fzero, fminbnd, fmincon) 并没有像我希望或期望的那样接近解决方案。

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

我想找到k >= 165.95which的值Lik(k)-L0 = 0Lik(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.96with Lik(k)-L0=-0.045。好吧,虽然不是很好。出于实际目的,如果没有大量的手动试验和错误,我不会知道如此精确的上限。如果我使用 interval (165.95,200)fzero返回k=167.19where Lik(k)-L0 = -0.65,这是相当糟糕的。我一直在将Display设置为iter来运行这些测试,这样我就可以看到发生了什么,并且似乎在第 4 次迭代时fzero命中167.19,然后在第 5 次迭代时停留在那里,这意味着k从一次迭代到下一次迭代的变化较小比TolX(设置为 0.001),因此程序结束。退出标志表明它成功收敛到一个解决方案。

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

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

非常感谢!

4

3 回答 3

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。我的第一语言不是英语,所以我为所犯的任何错误道歉。

干杯,克里斯蒂安

于 2015-02-24T13:29:03.460 回答
1

由于您似乎有一个“狂野”功能,该功能在该地区似乎是单调的,兴趣范围相当小,并且对精度的要求不是很高,我认为推荐蛮力方法的所有标准都已满足。

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

找到一个xmax上限和一个下限xmin,选择一个首选stepsize并评估您的函数

xmin:stepsize:xmax 

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

于 2013-02-21T14:34:24.693 回答
0

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

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

于 2013-02-22T11:45:58.170 回答