我不明白如何将界限融入到scipy的跳盆程序中。
我根据scipy的教程编写了下面的脚本,用来测试一维边界上的盆地跳跃。
from scipy.optimize import basinhopping
import matplotlib.pyplot as plt
class MyBounds:
def __init__(self, xmax, xmin ):
self.xmax = np.array(xmax)
self.xmin = np.array(xmin)
def __call__(self,**kwargs):
x = kwargs["x_new"]
tmax = bool(np.all(x <= self.xmax))
tmin = bool(np.all(x >= self.xmin))
return tmax and tmin
my_bounds = MyBounds([-4], [2])
func = lambda x: np.cos(14.5 * x - 0.3) + (x + 0.2) * x
x0=[1.]
minimizer_kwargs = {"method": "BFGS"}
ret = basinhopping(func, x0, minimizer_kwargs=minimizer_kwargs,
niter=2000, accept_test=my_bounds)
print("global minimum: x = %.4f, f(x) = %.4f" % (ret.x, ret.fun))
bounds = np.linspace(-5, 5, 100)
vals = [func(x) for x in bounds]
plt.plot(bounds, vals)
如果没有accept_test = my_bounds
,则输出为global minimum: x = -0.1951, f(x) = -1.0009
。如果包含这一行,则输出为global minimum: x = 1.0926, f(x) = 0.4259
。这没有意义--0.1951包含在[-4,2]中,所以应用边界时,它不应该是输出吗?
此外,将边界更改为[4,0]会输出global minimum: x = 1.0926, f(x) = 0.4259
。这甚至不在边界内。
在scipy里处理这个问题的正确方法是什么?
1条答案
按热度按时间3htmauhk1#
Basinhopping调用大都会Hasting以迭代方式生成步骤建议。这是随机的,在优化器的罩下发生。然而,这很可能是您的答案隐藏的地方。您可以使用函数揭示建议的序列(以及它们是否被接受)
以及修改该线
在您的程式码中。
这将打印迭代过程中每个步骤的状态。您将能够看到哪些步骤未被接受(使优化程序远离您期望的最小值)。
然而,
x = -0.1951
在区间[-4, 2]
内,x = 1.0926
和[0, 4]
也是如此,不幸的是,myBounds.__init__(self, xmax, xmin)
的参数顺序与直觉相反,先列出大的,后列出小的。