Scipy.optimize.minimize не дает минимальное значение, даже если он видит это значение - PullRequest
3 голосов
/ 13 мая 2019

Я использую scipy.optimize.minimize, чтобы найти оптимальные параметры для моей целевой функции.

Мой код:


import numpy as np
from scipy.optimize import minimize
from scipy.optimize import Bounds

bounds = Bounds([26,26,8,6,400,100,0,25,2],[36,38,28,28,1800,800,100,50,7])

energy_history = []
x_values = []

def objective(x):
    x_trail = x.reshape(1,-1)
    x_trail = sc_X.transform(x_trail)
    y_trail = regressorSVR.predict(x_trail)
    y_trail = y_trail.reshape(1,-1)
    y_trail = sc_Y.inverse_transform(y_trail)
    return y_trail[0]


def callback(x,y):
    fobj = objective(x)
    energy_history.append(fobj)
    x_values.append(x)

x0 = np.array([26,28,15,7,400,377,40,43,4.3])
res = minimize(objective, x0, method='trust-constr',
               options={'verbose': 1}, bounds=bounds,callback=callback)

optimal_values = res.x
energy = res.fun

При заданных начальных значениях полученное мной минимальное значение (res.fun) равно -7.1. Я создаю список (energy_history), чтобы увидеть, как он достигает этого значения. Я вижу некоторые значения, которые меньше -7,1 в этом списке, но тем не менее, почему -7,1 возвращается как минимальное значение.

image

Есть несколько раз, когда целевая функция достигла значения -21, но почему по-прежнему возвращается -7 как минимум?

1 Ответ

2 голосов
/ 05 июня 2019

Если мы посмотрим на документацию scipy.optimization, то увидим, что scipy.optimize.minimize указан в разделе локальная оптимизация .Основная проблема в том, что ваша проблема невыпуклая и, следовательно, scipy.optimize.minimize не может гарантировать правильную сходимость.Поскольку он также в значительной степени недифференцируем, многие алгоритмы не подходят вообще.

scipy.optimize действительно предоставляет некоторые глобальные алгоритмы оптимизации, хотя их можно найти на странице документации в разделе глобальная оптимизация , а именно basinhopping, brute и differential_evolution.Посмотрите на этот ответ для краткого объяснения.

В основном вы можете сначала попробовать brute, просто чтобы увидеть какие-либо систематические проблемы.Это в основном решение для перебора и будет медленным, но найдите свой минимум.Более сложный метод будет использовать differential_evolution.Поскольку ваша функция не совсем гладкая, basinhopping может не сработать, но все же стоит попробовать и, вероятно, сходится быстрее всего.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...