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, который я должен найти.

Приведенный выше код даст результат только тогда, когда x=1. Я пробовал с разной толерантностью и всеми тремя методами: L-BFGS-B, TNC и SLSQP. Это тема, которую я до сих пор просматривал: Scipy.optimize: как ограничить значения аргументов

Как я могу это исправить?

Я использую Spyder (Python 3.6).

введите описание изображения здесь


person Kim    schedule 21.09.2018    source источник
comment
print(f([2557, 1])) = 42690172880760.5, я бы не назвал это локальным минимумом ...   -  person Joe    schedule 21.09.2018
comment
Извините, я имел ввиду 2.557. Я редактировал   -  person Kim    schedule 21.09.2018


Ответы (2)


Вы только что столкнулись с проблемой локальной оптимизации: она сильно зависит от начальных (начальных) значений, которые вы передаете. Если вы укажете [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's basinhopping()

  • использовать алгоритм глобальной оптимизации и использовать его результат в качестве начального значения для локального алгоритма. Рекомендации - это DIRECT от NLopt или алгоритмы MADS (например, NOMAD). В scipy есть еще один shgo, который я еще не пробовал.

person Joe    schedule 21.09.2018
comment
Спасибо. На самом деле у меня много проблем с scipy.minimize, когда функции становятся длинными и сложными. Вы можете порекомендовать альтернативы? - person Kim; 21.09.2018
comment
Что вы имеете в виду под длинным и сложным? Есть и другие модули оптимизации, например nlopt. Но все они будут использовать вашу долгую и сложную функцию. В конце концов, методы, доступные в scipy, подходят для большого количества задач. - person Joe; 21.09.2018

Попробуйте scipy.optimize.basinhopping. Просто повторите процедуру минимизации несколько раз и получите несколько локальных минимумов. Минимальный - это глобальный минимум.

minimizer_kwargs = {"method": "L-BFGS-B"}
res=optimize.basinhopping(nethedge,guess,niter=100,minimizer_kwargs=minimizer_kwargs)
person 刘展旭    schedule 17.09.2019