Python оптимизирует несколько функций с общими переменными

я пытаюсь минимизировать (глобально) 3 функции, которые используют общие переменные, я пытался объединить их в одну функцию и минимизировать ее, используя L-BFGS-B (мне нужно установить границы для переменных), но оказалось очень сложно сбалансировать каждую параметр с весами, т.е. при минимизации одного другого не будет. Я также пытался использовать метод SLSQP для минимизации одного из них, устанавливая другие в качестве ограничений, но ограничения часто игнорируются/не выполняются. Вот что нужно свести к минимуму, вся математика делается в meritscalculation, а meritoflength, meritofROC, meritofproximity, heightorderreturned возвращаются из вычислений как глобальные.

def lengthmerit(x0):
    meritscalculation(x0)  
    print meritoflength
    return meritoflength

def ROCmerit(x0):
    meritscalculation(x0)
    print meritofROC
    return meritofROC

def proximitymerit(x0):
    meritscalculation(x0)
    print  meritofproximity+heightorder
    return meritofproximity+heightorder

я хочу минимизировать их все, используя общий x0 (с границами) в качестве независимой переменной, есть ли способ добиться этого?


person dilyar    schedule 14.02.2014    source источник


Ответы (2)


Это то, что вы хотите сделать?

minimize a * amerit(x) + b * bmerit(x) + c * cmerit(x)
over a, b, c, x:
    a + b + c = 1
    a >= 0.1, b >= 0.1, c >= 0.1 (say)
    x in xbounds

Если x равно [x0 x1 .. x9], установите новую переменную abcx = [a b c x0 x1 .. x9], ограничьте a + b + c = 1 с помощью штрафного члена, добавленного к целевой функции, и минимизируйте это:

define fabc( abcx ):
    """ abcx = a, b, c, x
        -> a * amerit(x) + ... + penalty 100 (a + b + c - 1)^2 
    """ 
    a, b, c, x = abcx[0], abcx[1], abcx[2], abcx[3:]  # split
    fa = a * amerit(x)
    fb = b * bmerit(x)
    fc = c * cmerit(x) 
    penalty = 100 * (a + b + c - 1) ** 2  # 100 ?
    f = fa + fb + fc + penalty
    print "fabc: %6.2g = %6.2g + %6.2g + %6.2g + %6.2g   a b c: %6.2g %6.2g %6.2g" % (
                f, fa, fb, fc, penalty, a, b, c )
    return f

и bounds = [[0.1, 0.5]] * 3 + xbounds, то есть каждый из a b c in 0.1 .. 0.5 или около того.
Длинные print должны показать вам, почему один из a b c приближается к 0 - может быть, один из amerit() bmerit() cmerit() намного больше остальных ? Plots вместо prints тоже было бы легко.

Резюме:
1) четко сформулировать проблему на бумаге, как указано выше
2) перевести это на python.

person denis    schedule 16.02.2014
comment
да, это то, что я хотел сделать, так что это в основном включает взвешивание в процесс оптимизации и позволяет компьютеру сбалансировать его, верно? А также есть большая разница между каждой функцией merit() (примерно порядка 1000), как это влияет на границы для a, b, c? это все еще будет [0.1, inf] или что-то еще? В любом случае, я сейчас тестирую этот метод, большое спасибо за ваши усилия, вы были очень полезны - person dilyar; 16.02.2014

вот результат некоторого масштабирования и взвешивания

целевая функция:

merit_function=wa*meritoflength*1e3+wb*meritofROC+wc*meritofproximity+wd*heightorder*10+1000 * (wa+wb+wc+wd-1) ** 2

вход:

abcdex=np.array(( 0.5, 0.5, 0.1, 0.3, 0.1...))

выход:

fun: array([ 7.79494644])

   x: array([  4.00000000e-01,   2.50000000e-01,   1.00000000e-01,
     2.50000000e-01...])


meritoflength : 0.00465499380753.  #target 1e-5, usually start at 0.1
meritofROC: 23.7317956542          #target ~1,  range <33
Heightorder: 0                     #target :strictly 0, range <28
meritofproximity : 0.0             #target:less than 0.02,   range <0.052

после нескольких прогонов я понял, что все веса имеют тенденцию оставаться на минимальных значениях границы, и я вернулся к ручной настройке проблемы масштабирования, с которой я начал.

Есть ли вероятность того, что моя функция оптимизации не находит истинный глобальный минимум?

вот как я минимизировал это:

minimizer_kwargs = {"method": "L-BFGS-B", "bounds": bnds, "tol":1e0 }

ret = basinhopping(merit_function, abcdex, minimizer_kwargs=minimizer_kwargs, niter=10)
zoom = ret['x']

res = minimize(merit_function, zoom, method = 'L-BFGS-B', bounds=bnds, tol=1e-6)
person dilyar    schedule 17.02.2014
comment
tol = 1 ?? попробуй 1е-4. Внимательно прочтите документацию по бассейну: для лучшего результаты T должны быть сопоставимы с расстоянием (по значению функции) между локальными минимумами -- оно может быть чувствительно к x0, размеру шага... тоже. И веса имеют тенденцию оставаться на минимальных значениях границы: они должны суммироваться до 1 ? в противном случае увеличьте штрафной коэффициент 100. - person denis; 17.02.2014
comment
причина, по которой я установил tol=1, заключается в том, чтобы сканировать больший домен с меньшей точностью (иначе будет потрачено много времени на попытки минимизировать большое значение), затем я использовал вторую функцию minimize, чтобы улучшить минимальное значение, возвращаемое первым минимизация с большей точностью - person dilyar; 17.02.2014
comment
Вы не можете ожидать хорошего минимума при времени выполнения, близком к 0, для многомерной задачи с инструментом с неизвестными параметрами. Я бы предложил начать с крошечной проблемы, где вы знаете ответ, чтобы получить некоторый опыт в отношении компромисса между значением функции и временем выполнения. - person denis; 17.02.2014