如何在有界的python优化中找到全局最小值? [英] how to find global minimum in python optimization with bounds?
问题描述
我有一个带有64个变量的Python函数,并且我尝试在最小函数中使用L-BFGS-B方法对其进行优化,但是该方法对初始猜测有很大的依赖性,并且未能找到全局最小值.
I have a Python function with 64 variables, and I tried to optimise it using L-BFGS-B method in the minimise function, however this method have quite a strong dependence on the initial guess, and failed to find the global minimum.
但是我喜欢它为变量设置界限的能力.有没有一种方法/函数可以找到全局最小值,同时具有变量的边界?
But I liked its ability to set bounds for the variables. Is there a way/function to find the global minimum while having boundaries for the variables ?
推荐答案
这可以通过scipy.optimize.basinhopping
完成. Basinhopping是用来查找目标函数的 global 最小值的函数.它使用函数scipy.optimize.minimize
进行重复的最小化,并在每次最小化后在坐标空间中采取随机步骤.通过使用实现边界的最小化器之一(例如L-BFGS-B),贝叶霍普仍然可以遵守边界.这是一些代码,展示了如何做到这一点
This can be done with scipy.optimize.basinhopping
. Basinhopping is a function designed to find the global minimum of an objective function. It does repeated minimizations using the function scipy.optimize.minimize
and takes a random step in coordinate space after each minimization. Basinhopping can still respect bounds by using one of the minimizers that implement bounds (e.g. L-BFGS-B). Here is some code that shows how to do this
# 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
上面的代码仅适用于简单的情况,但是如果使用盆地跳跃随机位移例程将您带到那儿,您仍然可以最终进入禁区.幸运的是,可以通过使用关键字take_step
The above code will work for a simple case, but you can still end up in a forbidden region if basinhopping random displacement routine takes you there. Luckily that can be overridden by passing a custom step taking routine using the keyword 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
这篇关于如何在有界的python优化中找到全局最小值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!