如何通过使用盆景来编写参数边界?

时间:2017-11-01 13:27:18

标签: python scipy

我在basinhopping中编写参数范围时遇到了困难。

(x0)=(a, b, c )

a = (0, 100)

b = (0, 0.100)

c = (0, 10)

from scipy.optimize import basinhopping

minimizer_kwargs = { "method": "Nelder-Mead" }

min = basinhopping(rmse, x0, minimizer_kwargs=minimizer_kwargs, T=0.5, stepsize=0.1, niter=200, disp=True)

2 个答案:

答案 0 :(得分:2)

这有多种方法,每种方法都有潜在的表现 不同的(在非凸的全局优化中很常见)。最好的方法总是考虑优化问题的先验信息!

最强大的一般方法(在我看来最好)将是以下组合:

  • A:内层:绑定约束的本地搜索
  • B:外层:绑定约束步骤

此优化程序的原作者说,仅依靠 A (与截至目前的其他答案一样)might fail

代码:

import numpy as np
from scipy.optimize import basinhopping


""" Example problem
    https://docs.scipy.org/doc/scipy-0.19.1/reference/generated/scipy.optimize.basinhopping.html
"""
def func2d(x):
    f = np.cos(14.5 * x[0] - 0.3) + (x[1] + 0.2) * x[1] + (x[0] + 0.2) * x[0]
    df = np.zeros(2)
    df[0] = -14.5 * np.sin(14.5 * x[0] - 0.3) + 2. * x[0] + 0.2
    df[1] = 2. * x[1] + 0.2
    return f, df

""" Example bounds """
bx0 = (-0.175, 1.)
bx1 = (-0.09, 1.)
bounds = [bx0, bx1]

""" Solve without bounds """
minimizer_kwargs = {"method":"L-BFGS-B", "jac":True}
x0 = [1.0, 1.0]
ret = basinhopping(func2d, x0, minimizer_kwargs=minimizer_kwargs, niter=200)
print(ret.message)
print("unconstrained minimum: x = [%.4f, %.4f], f(x0) = %.4f" % (ret.x[0], ret.x[1],ret.fun))


""" Custom step-function """
class RandomDisplacementBounds(object):
    """random displacement with bounds:  see: https://stackoverflow.com/a/21967888/2320035
        Modified! (dropped acceptance-rejection sampling for a more specialized approach)
    """
    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 """
        min_step = np.maximum(self.xmin - x, -self.stepsize)
        max_step = np.minimum(self.xmax - x, self.stepsize)

        random_step = np.random.uniform(low=min_step, high=max_step, size=x.shape)
        xnew = x + random_step

        return xnew

bounded_step = RandomDisplacementBounds(np.array([b[0] for b in bounds]), np.array([b[1] for b in bounds]))

""" Custom optimizer """
minimizer_kwargs = {"method":"L-BFGS-B", "jac":True, "bounds": bounds}

""" Solve with bounds """
x0 = [1.0, 1.0]
ret = basinhopping(func2d, x0, minimizer_kwargs=minimizer_kwargs, niter=200, take_step=bounded_step)
print(ret.message)
print("constrained minimum: x = [%.4f, %.4f], f(x0) = %.4f" % (ret.x[0], ret.x[1],ret.fun))

输出:

['requested number of basinhopping iterations completed successfully']
unconstrained minimum: x = [-0.1951, -0.1000], f(x0) = -1.0109
['requested number of basinhopping iterations completed successfully']
constrained minimum: x = [-0.1750, -0.0900], f(x0) = -0.9684

答案 1 :(得分:0)

您应该使用"bounds"中传递给minimizer_kwargs的{​​{1}}参数。这是一个例子:

scipy.optimize.minimize()

结果是

  

全局最小值:a = 1.0000,b = 1.0000 c = 1.0000 | f(x0)= 3.0000

没有边界,它是(清晰)0,0,0