如何在带边界的 python 优化中找到全局最小值?

新手上路,请多包涵

我有一个有 64 个变量的 Python 函数,我试图在最小化函数中使用 L-BFGS-B 方法对其进行优化,但是这种方法对初始猜测有很强的依赖性,并且未能找到全局最小值。

但我喜欢它为变量设置界限的能力。有没有一种方法/函数可以在为变量设置边界的同时找到全局最小值?

原文由 dilyar 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 614
1 个回答

这可以通过 scipy.optimize.basinhopping 来完成。 Basinhopping 是一种旨在找到目标函数的 全局 最小值的函数。它使用函数 scipy.optimize.minimize 重复最小化,并在每次最小化后在坐标空间中采取随机步骤。 Basinhopping 仍然可以通过使用实现边界的最小化器之一(例如 L-BFGS-B)来遵守边界。这是一些代码,展示了如何做到这一点

# an example function with multiple minima
def f(x): return x.dot(x) + sin(np.linalg.norm(x) * np.pi)

# the starting point
x0 = [10., 10.]

# the bounds
xmin = [1., 1.]
xmax = [11., 11.]

# rewrite the bounds in the way required by L-BFGS-B
bounds = [(low, high) for low, high in zip(xmin, xmax)]

# use method L-BFGS-B because the problem is smooth and bounded
minimizer_kwargs = dict(method="L-BFGS-B", bounds=bounds)
res = basinhopping(f, x0, minimizer_kwargs=minimizer_kwargs)
print res

上面的代码适用于一个简单的情况,但如果 basinhopping 随机位移例程将您带到那里,您仍然可能会进入禁区。幸运的是,可以通过使用关键字 take_step 传递自定义步骤来覆盖例程

class RandomDisplacementBounds(object):
    """random displacement with bounds"""
    def __init__(self, xmin, xmax, stepsize=0.5):
        self.xmin = xmin
        self.xmax = xmax
        self.stepsize = stepsize

    def __call__(self, x):
        """take a random step but ensure the new position is within the bounds"""
        while True:
            # this could be done in a much more clever way, but it will work for example purposes
            xnew = x + np.random.uniform(-self.stepsize, self.stepsize, np.shape(x))
            if np.all(xnew < self.xmax) and np.all(xnew > self.xmin):
                break
        return xnew

# define the new step taking routine and pass it to basinhopping
take_step = RandomDisplacementBounds(xmin, xmax)
result = basinhopping(f, x0, niter=100, minimizer_kwargs=minimizer_kwargs,
                      take_step=take_step)
print result

原文由 Jacob Stevenson 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题