我正在从事一个多目标优化项目,我偶然发现了对算法的需求,该算法给定一个函数作为输入,该函数可以在任意有限的次数(受计算能力限制)中返回该功能的本地或全局最小值的位置的均匀分布的采样。
如果您没有喜欢的语言,我更喜欢Python,并将任何建议移植到Python供我自己使用。否则,任何带有或不带有代码的答案都是可以接受的。
这类似于许多更容易回答的问题,因此我还有一些澄清的细节:
我们将定义一个具有已知局部最小值的函数,以生成一个简单的测试用例。
import numpy as np
def f(x: np.ndarray):
"""If x has shape (2,) returns distance from line y=x"""
return np.abs(np.diff(x))
def minima_sample(f, bounds, sample_size):
"""TODO"""
当我们尝试在单位正方形中找到3个均匀分布的,覆盖良好的点时,这些点位于f
的局部最小值(或全局范围,对于我的应用来说无关紧要)。 (可以视为oracle),最好的方法是返回线段的两个端点,这些端点代表所有最小值以及正好位于它们之间的点。同样得4分。
>>> print(minima_sample(f, [(0,1), (0,1)], 3))
array([[0. , 0. ],
[0.5, 0.5],
[1. , 1. ]])
>>> print(minima_sample(f, [(0,1), (0,1)], 4))
array([[0. , 0. ],
[0.33333333, 0.33333333],
[0.66666667, 0.66666667],
[1. , 1. ]])
有两类与此问题密切相关的算法:
示例包括梯度下降,各种各样的拟牛顿法,“基于斑点”的不可微搜索算子,等等。整洁的是,它们实际上可以相对轻松地用来回答这个问题。只需在随机起点处运行本地解算器,直到解决方案的边界大约不会增大,然后继续运行,直到在该边界中有足够的点均匀分布为止。将精力集中在空白处以提高效率。
从技术上讲,这些可以用来建立答案,但是IMO这是一个效率很低的策略。您至少需要与请求点数一样多的局部最小化步骤(如果功能不当,则需要更多),并且所有信息在局部最小化之间都被丢弃,因此您不能使用一个最小值的位置来指导寻找另一个。也许这实际上是最佳选择,但我怀疑还有更好的选择。
示例包括盆地跳跃,模拟退火等。从表面上看,它们似乎是正确的方法,因为它们检查了大量局部最小值,并最终确定了其中的最小最小值。可以简单地返回获得的局部最小值的合适子集。但是,通过设计,他们选择本地极小值的方式可能会朝着全局极小值迈进。根据定义,这会尝试使搜索产生偏差并对局部最小值进行不均匀采样。
出于个人好奇心,我对您认为可能适用的任何算法都感兴趣。实际上,优化例程的效率与针对特定问题的量身定制密切相关。我想到的特定功能有很多约束和特殊属性,可能会有所作为:
我目前已实现了 2.1 中提到的随机重启方法。从技术上讲,它可以运行,但是比我想要的要慢。从算法的角度来看,它也不是优雅或令人满意的。
随机重启方法并不是均匀采样,而是通过修改起始位置以尝试突破现有解决方案的边界并填充这些解决方案中的空白(使用减少的空间进行邻近度计算),可以获得合理的覆盖率。算上Jacobian和Hessian,对于简单问题,每个样本点使用〜5个函数求值,对于复杂问题,使用〜80个函数求值。目标是利用我们当前正在丢弃的一些额外信息,将约80个信息减少到更可管理的水平。我希望最大加速速度约为16倍(或者说硬币的另一端具有处理较大问题的能力)。
我曾经想过要找到一个局部最小值,然后通过沿方向导数为0的方向“跟随”它所处的流形(因为局部最小值和全局最小值是全部为0)。对于一维流形来说,这已经足够容易实现了,但是我还没有想出一种令人满意的方法来处理更复杂的搜索空间而不加倍返回。
令我惊讶的是,针对人口的进化算法可能具有针对个人的基于牛顿的本地搜索组件。进化算法通常具有的与随机搜索的关系以及对参数的极端敏感性使我感到警觉。
是否存在解决此类问题的标准方法?如果没有,我是否可以权衡其优点和缺点的适用算法的简短列表?我的Google-foo出现了问题,而我最初的预感并没有取得很好的结果。解决这个问题时,我还有什么要考虑的吗?甚至书/参考书/博客/播客推荐总比没有好。
预先感谢您的努力。