Как я должен scipy.optimize многомерной и недифференцируемой функции с границами?

Я сталкиваюсь со следующей проблемой оптимизации:

Функция target - это многомерная и недифференцируемая функция, которая принимает в качестве аргумента список скаляров и возвращает скаляр. Это недифференцируемо в том смысле, что вычисления внутри функции основаны на пандах и серии вращающихся, стандартных и т. Д. Действий.

Псевдокод ниже:

def target_function(x: list) -> float:
    # calculations
    return output

Кроме того, каждый компонент аргумента x имеет свои собственные границы, определенные как кортеж (min, max). Так как же мне использовать библиотеку scipy.optimize, чтобы найти глобальный минимум этой функции? Какие-нибудь другие библиотеки могут помочь?

Я уже попробовал scipy.optimize.brute, который взял меня навсегда и scipy.optimize.minimize, который никогда не давал, казалось бы, правильного ответа.

1 ответ

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

Дифференциальная эволюция - это стохастический метод, который должен работать лучше, чем перебор, но все же может потребовать большого количества оценок целевых функций. Если вы хотите использовать его, вы должны поиграть с параметрами и посмотреть, что лучше всего подойдет для вашей проблемы. Это имеет тенденцию работать лучше, чем другие методы, если вы знаете, что ваша целевая функция не является "гладкой": в функции или ее производных могут быть разрывы.

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

Преимущество scipy.optimize.basinhopping рутина состоит в том, что это очень настраиваемо. Ты можешь использовать take_step определить произвольный случайный прыжок, accept_test переопределить тест, используемый для принятия решения о том, следует ли продолжить или отменить результаты случайного скачка и расслабления, и minimizer_kwargs настроить локальное поведение минимизации. Например, вы можете переопределить take_step чтобы оставаться в пределах своих границ, а затем, возможно, выбрать минимизатор L-BFGS-B, который может численно оценить градиент вашей функции, а также определить границы параметров. L-BFGS-B работает лучше, если вы установите градиент, но я использовал его без градиента, и он все еще способен хорошо минимизировать. Обязательно прочитайте обо всех параметрах в локальной и глобальной подпрограммах оптимизации и отрегулируйте такие параметры, как допуски, как приемлемые, для повышения производительности.

Другие вопросы по тегам