首页 > 解决方案 > scipy.optimize 陷入局部最小值。我能做些什么?

问题描述

 from numpy import *; from scipy.optimize import *; from math import *
def f(X):
    x=X[0];    y=X[1]
    return x**4-3.5*x**3-2*x**2+12*x+y**2-2*y

bnds = ((1,5), (0, 2))
min_test = minimize(f,[1,0.1], bounds = bnds); 
print(min_test.x)

我的函数f(X)有一个x=2.557, y=1我应该能够找到的局部最小值。

上面显示的代码只会给出结果 where x=1。我尝试了不同的公差和三种方法:L-BFGS-B、TNC 和 SLSQP。到目前为止,这是我一直在关注的主题: Scipy.optimize: how to restrict argument values

我怎样才能解决这个问题?

我正在使用 Spyder(Python 3.6)。

在此处输入图像描述

标签: pythonscipyspyderminimization

解决方案


您刚刚遇到了局部优化的问题:它在很大程度上取决于您传入的起始(初始)值。如果您提供[2, 1]它,它将找到正确的最小值。

常见的解决方案是:

  • 在循环中使用您的优化,在您的边界内随机起点

    import numpy as np
    from numpy import *; from scipy.optimize import *; from math import *
    
    def f(X):
        x=X[0];    y=X[1]
        return x**4-3.5*x**3-2*x**2+12*x+y**2-2*y
    
    bnds = ((1,3), (0, 2))
    
    for i in range(100):
    
        x_init = np.random.uniform(low=bnds[0][0], high=bnds[0][1])
        y_init = np.random.uniform(low=bnds[1][0], high=bnds[1][1])
    
        min_test = minimize(f,[x_init, y_init], bounds = bnds)
    
        print(min_test.x, min_test.fun)
    
  • 使用可以摆脱局部最小值的算法,我可以推荐 scipy 的basinhopping()

  • 使用全局优化算法并将其结果用作局部算法的初始值。推荐的是 NLoptDIRECT或 MADS 算法(例如NOMAD)。scipy 中还有另一个shgo,我还没有尝试过。


推荐阅读