Ответ 1
Функция, которую вы тестируете, использует подход, называемый Metropolis-Hastings, который можно модифицировать в процедуру, называемую имитированным отжигом, которая может оптимизировать функции стохастическим способом.
То, как это работает, выглядит следующим образом. Сначала вы выбираете точку, как ваша точка x0
. С этого момента вы генерируете случайное возмущение (это называется "предложением" ). После того, как будет предложенное возмущение, вы получите своего кандидата за новый пункт, применив возмущение к вашему текущему результату. Таким образом, вы можете думать об этом как x1 = x0 + perturbation
.
В обычном старом градиентном спуске термин perturbation
является просто детерминистически рассчитанной величиной, как шаг в направлении градиента. Но в Metropolis-Hastings perturbation
генерируется случайным образом (иногда с использованием градиента в качестве подсказки о том, куда случайным образом идти... но иногда просто случайно, без подсказок).
В этот момент, когда у вас есть x1
, вы должны спросить себя: "Я сделал что-то хорошее, случайно нарушив x0
, или я просто все испортил?" Одна из них связана с тем, что вы придерживаетесь некоторых границ, например, вашей mybounds
функции. Другая его часть связана с тем, насколько лучше/хуже значение целевой функции стало в новой точке.
Таким образом, существует два способа отклонения предложения x1
: во-первых, это может нарушить установленные вами границы и быть неосуществимой точкой определения проблемы; во-вторых, на этапе принятия/отклонения оценки в Metropolis-Hastings это может быть очень плохой момент, который должен быть отклонен. В любом случае вы отклоните x1
и вместо этого установите x1 = x0
и притворитесь, будто вы просто остановились в том же месте, чтобы повторить попытку.
Контрастируйте это с помощью метода градиентного типа, где вы определенно, независимо от того, всегда делаете хотя бы какое-то движение (шаг в направлении градиента).
Ну, ладно. С этим все в стороне, подумайте о том, как это происходит с функцией basinhopping
. Из документации мы можем видеть, что к типичному условию приема обращается аргумент take_step
и в документации, говорящей так: "Обычная процедура принятия шага по умолчанию - это случайное смещение координат, но другие алгоритмы принятия шагов могут быть лучше для некоторых системы". Таким образом, даже если вы не можете проверить свой mybounds
bounds checker, функция будет делать случайное смещение координат, чтобы создать новую точку, чтобы попробовать. А так как градиент этой функции является только константой 1
, она всегда будет делать те же большие шаги в направлении отрицательного градиента (для минимизации).
На практическом уровне это означает, что предлагаемые точки для x1
всегда будут совершенно вне интервала [0,1]
, и ваш проверитель всегда наложит вето на них.
Когда я запускаю свой код, я вижу, что это происходит все время:
In [5]: spo.basinhopping(f1,x0,accept_test=mybounds,callback=print_fun,niter=200,minimizer_kwargs=minimizer_kwargs)
at minima -180750994.1924 accepted 0
[ -1.80746874e+08]
False
at minima -180746877.5530 accepted 0
[ -1.80746873e+08]
False
at minima -180746877.3896 accepted 0
[ -1.80750991e+08]
False
at minima -180750994.7281 accepted 0
[ -1.80746874e+08]
False
at minima -180746878.2433 accepted 0
[ -1.80746874e+08]
False
at minima -180746877.5774 accepted 0
[ -1.80746874e+08]
False
at minima -180746878.3173 accepted 0
[ -1.80750990e+08]
False
at minima -180750994.3509 accepted 0
[ -1.80750991e+08]
False
at minima -180750994.6605 accepted 0
[ -1.80746874e+08]
False
at minima -180746877.6966 accepted 0
[ -1.80746874e+08]
False
at minima -180746877.6900 accepted 0
[ -1.80750990e+08]
False
at minima -180750993.9707 accepted 0
[ -1.80750990e+08]
False
at minima -180750994.0494 accepted 0
[ -1.80750991e+08]
False
at minima -180750994.5824 accepted 0
[ -1.80746874e+08]
False
at minima -180746877.5459 accepted 0
[ -1.80750991e+08]
False
at minima -180750994.6679 accepted 0
[ -1.80750991e+08]
False
at minima -180750994.5823 accepted 0
[ -1.80750990e+08]
False
at minima -180750993.9308 accepted 0
[ -1.80746874e+08]
False
at minima -180746878.0395 accepted 0
[ -1.80750991e+08]
False
# ... etc.
Таким образом, он никогда не принимает точки позиции. Вывод не говорит вам, что он нашел решение. Это говорит вам, что случайное возмущение, чтобы исследовать возможные решения, приводит к появлению точек, которые выглядят лучше и лучше для оптимизатора, но которые не соответствуют вашим критериям. Он не может найти свой путь обратно к [0,1]
, чтобы получить точки, которые удовлетворяют mybounds
.