Как я должен 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 работает лучше, если вы установите градиент, но я использовал его без градиента, и он все еще способен хорошо минимизировать. Обязательно прочитайте обо всех параметрах в локальной и глобальной подпрограммах оптимизации и отрегулируйте такие параметры, как допуски, как приемлемые, для повышения производительности.