Неверные границы значений параметров при использовании функции Mystic's diffrential Evolution - PullRequest
0 голосов
/ 26 января 2019

В настоящее время я использую Сетевую Теорию Химических Реакций (CRNT) для изучения бистабильности при передаче сигналов инсулина. Используя CRNT, я пришел к тому, что мне нужно решить глобальную задачу оптимизации с ограничениями для получения седловых узлов. Я рассмотрел несколько алгоритмов для решения моей проблемы, однако, поскольку моя задача нелинейная и невыпуклая с возможностью быть мультимодальной, я обнаружил, что подходит лишь несколько методов. Я обнаружил, что дифференциальная эволюция (DE) кажется наиболее подходящей для начала. Поскольку у меня нет опыта в области оптимизации, я искал библиотеку на python, которая могла бы действовать как своего рода черный ящик для моих целевых функций и ограничений. После быстрого поиска я обнаружил, что Mystic предоставляет функцию для DE, которая выглядит довольно простой в использовании. Однако, когда я реализую функцию DE, я получаю значения для моих параметров, которые выходят за пределы, которые я предписал.

Я уже реализовал функцию DE для очень простой задачи и получаю отличные результаты. В дополнение к этому я также пробовал большие значения для npop, gtol и maxiter. Значение около 5000 для npop предоставляет значения, близкие к желаемому диапазону, но есть некоторые значения, которые все еще не находятся в указанном диапазоне (возможно, очень большое значение npop даст мне желаемые результаты). Кажется, ничто не решает эту проблему, когда значения параметров находятся за пределами указанных мной границ. Ниже приведен точный код, который я запускаю.

import mystic
from mystic.penalty import quadratic_equality
from mystic.solvers import diffev2
from mystic.constraints import as_constraint

def objective(x):
    k15,k51,k16,k82,k28,k27,k93,k39,k34,a1,a2,c4 = x
    c1 = -a2*(k34 + k39)/(c4*k34*k93)
    c2 = c4*k34*k93*(a1 - a2)*(k15 + k16)/(a2*k16*k51*(k34 + k39))
    c3 = -a1*(k27 + k28)/(c4*k27*k82)
    c5 = -(a1 - a2)/k16
    c6 = -a1/k27
    c7 = -a2/k34
    return 1e10*((1.0*c1**2*c4*k34*k51*k82*k93 + 1.0*c1**2*k27*k34*k51*k93 + 1.0*c1**2*k28*k34*k51*k93 - 2.0*c1*c2*c4*k16*k51*k82*k93 +
     1.0*c1*c2*c4*k34*k51*k82*k93 - 2.0*c1*c2*k16*k27*k51*k93 - 2.0*c1*c2*k16*k28*k51*k93 + 1.0*c1*c2*k27*k34*k51*k93 + 1.0*c1*c2*k28*k34*k51*k93 -
     2.0*c1*c3*c4*k27*k51*k82*k93 - 1.0*c1*c3*c4*k34*k51*k82*k93 - 1.0*c1*c3*k27*k34*k51*k82 - 1.0*c1*c3*k27*k39*k51*k82 - 1.0*c1*c4**2*k34*k51*k82*k93 +
     1.0*c1*c4*k15*k34*k82*k93 + 1.0*c1*c4*k16*k34*k82*k93 - 1.0*c1*c4*k27*k34*k51*k93 - 1.0*c1*c4*k28*k34*k51*k93 + 1.0*c1*k15*k27*k34*k93 + 1.0*c1*k15*k28*k34*k93 +
     1.0*c1*k16*k27*k34*k93 + 1.0*c1*k16*k28*k34*k93 - 1.0*c2*c3*k16*k34*k51*k82 - 1.0*c2*c3*k16*k39*k51*k82 - 1.0*c2*c3*k27*k34*k51*k82 - 1.0*c2*c3*k27*k39*k51*k82 -
     1.0*c2*c4*k16*k34*k51*k82 - 1.0*c2*c4*k16*k39*k51*k82 - 1.0*c2*k16*k27*k34*k51 - 1.0*c2*k16*k27*k39*k51 - 1.0*c2*k16*k28*k34*k51 - 1.0*c2*k16*k28*k39*k51 -
     2.0*c3*c4*k15*k27*k82*k93 - 1.0*c3*c4*k15*k34*k82*k93 - 2.0*c3*c4*k16*k27*k82*k93 - 1.0*c3*c4*k16*k34*k82*k93 - 1.0*c3*k15*k27*k34*k82 - 1.0*c3*k15*k27*k39*k82 -
     1.0*c3*k16*k27*k34*k82 - 1.0*c3*k16*k27*k39*k82 - 1.0*c4**2*k15*k34*k82*k93 - 1.0*c4**2*k16*k34*k82*k93 - 1.0*c4*k15*k27*k34*k93 - 1.0*c4*k15*k28*k34*k93 -
     1.0*c4*k16*k27*k34*k93 - 1.0*c4*k16*k28*k34*k93)**2/(k16**2*k27**2*k34**2*k51**2*k82**2*k93**2))

#c1
def penalty1(x):
    k15,k51,k16,k82,k28,k27,k93,k39,k34,a1,a2,c4 = x
    return -a2*(k34 + k39)/(c4*k34*k93)
#c2
def penalty2(x):
    k15,k51,k16,k82,k28,k27,k93,k39,k34,a1,a2,c4 = x
    return c4*k34*k93*(a1 - a2)*(k15 + k16)/(a2*k16*k51*(k34 + k39))

#c3
def penalty3(x):
    k15,k51,k16,k82,k28,k27,k93,k39,k34,a1,a2,c4 = x
    return -a1*(k27 + k28)/(c4*k27*k82)

#c5
def penalty4(x):
    k15,k51,k16,k82,k28,k27,k93,k39,k34,a1,a2,c4 = x
    return -(a1 - a2)/k16

#c6
def penalty5(x):
    k15,k51,k16,k82,k28,k27,k93,k39,k34,a1,a2,c4 = x
    return -a1/k27

#c7
def penalty6(x):
    k15,k51,k16,k82,k28,k27,k93,k39,k34,a1,a2,c4 = x
    return -a2/k34

@quadratic_equality(penalty1, k=1e12)
@quadratic_equality(penalty2, k=1e12)
@quadratic_equality(penalty3, k=1e12)
@quadratic_equality(penalty4, k=1e12)
@quadratic_equality(penalty5, k=1e12)
@quadratic_equality(penalty6, k=1e12)
def penalty(x):
    return 0.0

solver = as_constraint(penalty)

b1 = (1e-1,1e2)
b2 = (1e-1,1e2)
b3 = (1e-1,1e2)
b4 = (1e-1,1e2)
b5 = (1e-1,1e2)
b6 = (1e-1,1e2)
b7 = (1e-1,1e2)
b8 = (1e-1,1e2)
b9 = (1e-1,1e2)
b10 = (-1e-1,0)
b11 = (-1e-1,0)
b12 = (1e-1,1e2)


bounds = [b1,b2,b3,b4,b5,b6,b7,b8,b9,b10,b11,b12]

#npop should be at least 10*dim, where dim is the number of parameters
result = diffev2(objective, x0=bounds, bounds=bounds, penalty=penalty, npop=120, disp=False, full_output=True, gtol=100, maxiter=6000)

print("")
print("The minimized objection function value:")
print(result[1])
print("")
print("Parameter values:")
print(result[0])

Запустив это, я получаю следующий вывод.

Минимизированное значение функции возражения +1,216082506137729

Значения параметров [1.07383892e-01 9.99893116e + 01 8.88912946e + 01 9.99859090e + 01 1.09022526e-01 9.99587677e + 01 9.70349805e + 01 1.23842240e + 01 4.72484236e + 00 -1.01491728e-08 -1.01491720e-08.0000 01]

Как видно, вектор, заданный для значений параметров, обеспечивает значения -1.01491728e-08 и -1.01491720e-08, которые должны находиться в диапазоне (-0,1,0).

Я просто неправильно реализовал или неверно истолковал что-то в Mystic или мне нужно изучить другой алгоритм для решения моей проблемы оптимизации? Если вы предполагаете, что другой алгоритм будет лучше, вы предлагаете использовать Scatter Search (SS)? Кроме того, Mystic предоставляет функции, которые могут выполнять SS, или мне нужно было бы реализовать это самостоятельно?

Любая помощь будет оценена.

1 Ответ

0 голосов
/ 26 января 2019

Я mystic автор.Первое, что нужно отметить, это то, что вы используете penalty функции.Они не ограничивают пространство поиска для оптимизатора, они добавляют наказание к цели, которая «поощряет» его не находить решения в пространстве, где штраф не равен нулю.Итак, это первое, что нужно отметить.Если вы хотите ограничить решения только областями пространства, в которых эти ограничения действительны, вместо этого используйте constraints.

Однако это не решает, почему ваши bounds не были соблюдены.Они должны быть.Есть причины, по которым их может и не быть, например, вы не нашли хороших решений в ходе оптимизации.Хорошо известно, что DE может работать плохо для большого числа параметров с жесткими границами.Я бы прикрепил монитор, чтобы вы могли видеть, как параметры меняются со временем.И, в этом случае, если вы видите, что все параметры переходят от «действительных» к некоторым за пределами границ, то вы нашли ошибку, и, пожалуйста, сообщите об этом на GitHub.

Даже в последнем случае,Вы могли бы усилить ограничения еще сильнее, добавив объект ограничения, который использует последовательность неравенств, чтобы гарантировать, что параметры находятся в выбранном диапазоне ... однако, я подозреваю, что происходит что-то, что можно различить, прикрепив VerboseMonitor.

mystic предоставляет нечто похожее на алгоритм поиска разброса.Проверьте решатели mystic.ensemble.

ОБНОВЛЕНИЕ: показаны результаты, которые я последовательно получаю

>>> mon = mystic.monitors.VerboseMonitor()
>>> result = diffev2(objective, x0=bounds, bounds=bounds, penalty=penalty, npop=40, disp=False, full_output=True, gtol=100, maxiter=6000, itermon=mon)
Generation 0 has ChiSquare: 2070417340.327223
Generation 10 has ChiSquare: 2070417340.327223
Generation 20 has ChiSquare: 1504378818.925922
Generation 30 has ChiSquare: 49226009.999661
Generation 40 has ChiSquare: 49226009.999661
Generation 50 has ChiSquare: 49226009.999661
Generation 60 has ChiSquare: 49226009.999661
Generation 70 has ChiSquare: 26549433.119812
Generation 80 has ChiSquare: 15513978.070527
Generation 90 has ChiSquare: 2637293.216637
Generation 100 has ChiSquare: 2466027.220625
Generation 110 has ChiSquare: 857082.416445
Generation 120 has ChiSquare: 409397.900243
Generation 130 has ChiSquare: 61023.902060
Generation 140 has ChiSquare: 61023.902060
Generation 150 has ChiSquare: 34911.899051
Generation 160 has ChiSquare: 22564.321601
Generation 170 has ChiSquare: 3078.667678
Generation 180 has ChiSquare: 3078.667678
Generation 190 has ChiSquare: 1233.029461
Generation 200 has ChiSquare: 1233.029461
Generation 210 has ChiSquare: 161.823695
Generation 220 has ChiSquare: 43.540529
Generation 230 has ChiSquare: 42.662921
Generation 240 has ChiSquare: 16.988486
Generation 250 has ChiSquare: 16.988486
Generation 260 has ChiSquare: 16.988486
Generation 270 has ChiSquare: 8.237803
Generation 280 has ChiSquare: 8.237803
Generation 290 has ChiSquare: 5.994087
Generation 300 has ChiSquare: 5.597002
Generation 310 has ChiSquare: 5.597002
Generation 320 has ChiSquare: 4.998805
Generation 330 has ChiSquare: 4.722383
Generation 340 has ChiSquare: 4.544368
Generation 350 has ChiSquare: 4.544368
Generation 360 has ChiSquare: 4.332436
Generation 370 has ChiSquare: 3.711041
Generation 380 has ChiSquare: 1.618530
Generation 390 has ChiSquare: 1.342488
Generation 400 has ChiSquare: 1.279087
Generation 410 has ChiSquare: 1.266669
Generation 420 has ChiSquare: 1.233121
Generation 430 has ChiSquare: 1.225398
Generation 440 has ChiSquare: 1.225398
Generation 450 has ChiSquare: 1.224930
Generation 460 has ChiSquare: 1.220611
Generation 470 has ChiSquare: 1.220611
Generation 480 has ChiSquare: 1.219702
Generation 490 has ChiSquare: 1.217958
Generation 500 has ChiSquare: 1.217265
Generation 510 has ChiSquare: 1.217095
Generation 520 has ChiSquare: 1.216879
Generation 530 has ChiSquare: 1.216421
Generation 540 has ChiSquare: 1.216096
Generation 550 has ChiSquare: 1.215315
Generation 560 has ChiSquare: 1.215274
Generation 570 has ChiSquare: 1.215125
STOP("ChangeOverGeneration with {'tolerance': 0.005, 'generations': 100}")
>>> lb,ub = zip(*bounds)
>>> result[0] < ub
array([ True,  True,  True,  True,  True,  True,  True,  True,  True,
        True,  True,  True])
>>> result[0] > lb
array([ True,  True,  True,  True,  True,  True,  True,  True,  True,
        True,  True,  True])
>>> 
...