繁体   English   中英

最小化一个 function

[英]Minimize a function

假设给定一个单一变量的 function 和 arguments a 和 b,并被要求找到 function 在区间 [a, b] 上的最小值。 (您可以假设参数是双精度的,尽管在我的应用程序中我可能需要使用任意精度的库。)

一般来说,这是一个难题,因为函数可能很奇怪。 这个问题的一个简单版本是最小化 function 假设它是连续的(没有间隙或跳跃)和单峰(有一个唯一的最小值;在最小值的左侧,function 正在减小,在右侧它是增加)。 有没有一种好方法可以解决这个更容易(但可能并不容易?)的问题?

假设 function 可能难以计算,但存储您计算的答案并不是特别昂贵。 (显然,最好不要制作巨大的键/值对 arrays。)

在幸运的情况下改进算法的好点子很好(例如:导数存在,function 是平滑/解析的,导数可以以封闭形式计算,在评估 function 时可以免费计算导数) .

您描述的版本只有一个最小值,很容易解决。

这个想法是这样的。 假设我有 3 个点, a < b < cf(b) < f(a)f(b) < f(c) 那么真正的最小值在ac之间。 此外,如果我在区间的某处选择另一个点d ,那么我可以丢弃ad中的一个,并且仍然有一个中间有真正最小值的区间。 随着我进行更多迭代,我的近似值将呈指数级快速提高。

我们还没有完全从这个开始。 我们从 2 点开始, ab ,并且知道答案在中间的某个地方。 取中点。 如果f低于端点,我们就进入了我上面讨论的情况。 否则,它必须低于端点之一,高于另一个端点。 我们可以丢弃更高的端点并重复。

如果 function 很好,即单峰且严格单调(即严格地从最小值的左侧减少并严格地向右增加),那么您可以通过二进制搜索找到最小值:

  • 设置x = (ba)/2
  • 测试x是在最小值的右侧还是左侧
  • 如果x在最小值的左边: b = x
  • 如果x在最小值的右边: a = x
  • 从头开始重复,直到你感到无聊
  • 最小值在x

要测试x是否在最小值的左/右,请发明一个小值epsilon并检查f(x - epsilon) < f(x + epsilon)是否。 如果是,则最小值在左侧,否则在右侧。 “直到你感到无聊”,我的意思是:发明另一个小值delta并在fabs(f(x - epsilon) - f(x + epsilon)) < delta时停止。


请注意,在您对 function f 的行为一无所知的一般情况下,无法确定 f 的重要属性。 好吧,除非您愿意尝试所有可能的输入。 有关详细信息,请参阅赖斯定理

Boost 项目有一个可能有用的Brent 算法的实现。 似乎假设 function 是连续的,并且在输入间隔中没有最大值(只有最小值)。

不是直接的答案,而是指向更多阅读的指针:

对于 function 可微分两次(并且两个导数可以轻松计算)的特殊情况,可以使用 牛顿法进行优化,即基本上找到一阶导数的根(这是最小值的必要条件)。

关于一般情况,请注意“奇怪”的极端情况是 function,它在任何地方都是连续的,并且即使不是不可能找到最小值也非常困难(在有限时间内)。 所以我想你应该至少对你试图最小化的 function 做出一些假设。

您想要的是优化单峰 function 正确的算法类似于 btilly 的,但你需要加分。

Take 4 points a < b < c < d.
We want to minimize f in [a,d].

If f(b) < f(c) we know the minimum is in [a, c]
If f(b) > f(c) "  "    "   "       is in [b, d]

这可以自己给出一个算法,但是有一个很好的技巧涉及黄金比例,它允许你重用中间值(在某种程度上你只需要计算 f 每次迭代而不是两次)

如果您有 function 的表达式,则有基于区间分析的全局优化算法。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM