Остановите Scipy diff_evolution () через временной интервал - PullRequest
0 голосов
/ 25 марта 2020

На мой вопрос уже частично ответили здесь . Мне просто нужно расширить ответ на другую функцию Scipy. (Scipy 1.4.0, Python 3.7 на Windows 10)

Обращаясь к ответу @ ali_m , я попытался применить ту же идею к differential_evolution() Scipy функция, которая также имеет аргумент callback.

Я хотел бы убедиться, что моя функция Scipy differential_evolution() перестает работать после определенного периода времени. В этом случае я выбрал функцию Розенброка с 40 входными параметрами и порогом 0,3 секунды, чтобы выделить то, что происходит.

import numpy as np
from scipy.optimize import differential_evolution, rosen
import time
import warnings

class TookTooLong(Warning):
    pass

class MinimizeStopper(object):
    def __init__(self, max_sec=0.3):
        self.max_sec = max_sec
        self.start = time.time()
    def __call__(self, xk=None, convergence=None):
        elapsed = time.time() - self.start
        if elapsed > self.max_sec:
            warnings.warn("Terminating optimization: time limit reached",
                          TookTooLong)
        else:
            print("Elapsed: %.3f sec" % elapsed)

n_var = 40 

upper_bound_array = np.ones(n_var) * 5
lower_bound_array = np.ones(n_var) * -5
bounds = Bounds(lower_bound_array, upper_bound_array)

# function call
res = differential_evolution(Rosen, bounds, strategy='best1bin',disp=False,
                                    callback=MinimizeStopper(), 
                                    maxiter=1000000) 

В результате я не получаю ошибок, но кажется, что те же логики c используется в Scipy minimize() здесь не работает. Чтобы быть более точным c, когда я запускаю программу, даже после выдачи предупреждения, программа молча продолжает вычислять все необходимые итерации, пока проблема оптимизации не сходится.

Кто-нибудь знает, почему в этом случае это не работает как в minimize() случае? Буду очень признателен за вашу помощь.

Заранее спасибо

1 Ответ

0 голосов
/ 26 марта 2020

Проблема в том, что callback должен возвращать True или False в зависимости от того, должна ли оптимизация быть остановлена ​​или нет (соответственно).

В вашем случае, MinimizeStopper ничего не возвращает и просто выдает предупреждение. Таким образом, вы также должны жестко закодировать возвраты True / False.

Попробуйте это

class MinimizeStopper(object):
    def __init__(self, max_sec=0.3):
        self.max_sec = max_sec
        self.start = time.time()

    def __call__(self, xk=None, convergence=None):
        elapsed = time.time() - self.start
        if elapsed > self.max_sec:
            print("Terminating optimization: time limit reached")
            return True
        else:
            # you might want to report other stuff here
            # print("Elapsed: %.3f sec" % elapsed)
            return False

Есть пара вещей, которые следует учитывать:

  1. , если только вы указываете polish=False в качестве входных данных для differential_evolution(), операция полировки все еще выполняется после остановки эволюции: это добавляет дополнительное время
  2. callback запускается после завершения оценки каждого поколения: это может превышать лимит, когда итерация занимает значительное время.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...