【问题标题】:Scipy.optimize.minimize function to determine multiple variablesScipy.optimize.minimize 函数确定多个变量
【发布时间】:2017-12-30 22:54:37
【问题描述】:

我想找出最佳参数,例如 bo、ho、t1 和 t2,以使误差函数 (f) 最小(即零或接近零)。完整代码如下,

import numpy
import scipy.optimize as optimize

#OPTIMISATION USING SCIPY
def Obj_func(x):
    bo,ho,t1,t2=x
    f=-321226.4817 + (10400000*bo*ho**3 - 10400000*(bo - 2*t2)*(ho - 2*t1)**3)/(125 + (10400000*bo*ho**3 - 10400000*(bo - 2*t2)*(ho - 2*t1)**3)/(1563920*t1*(bo - 2*t2)))
    return f

initial_guess=[2,2,0.2,0.2]
cons = ({'type': 'eq', 'fun': lambda bo,ho,t1,t2: (bo*ho - (bo - 2*t2)*(ho - 2*t1)-7.55)})
bnds = ((0, None), (0, None),(0, None), (0, None)) #all four variables are positive and greater than zero
#Always t1 and t2 should always be lesser than bo and ho
#res=optimize.minimize(Obj_func, method='SLSQP',initial_guess, bounds=bnds,constraints=cons)
res=optimize.minimize(Obj_func,initial_guess, bounds=bnds,constraints=cons)
print ("Result",res)

我在这里遇到了一些问题, Q1。为 cons 创建的 lambda 函数给了我一个错误,指出“TypeError: () 缺少 3 个必需的位置参数:'ho'、't1' 和 't2'”。为什么会这样?即使我正确地遵循了语法,我还是缺少一些东西。 Q2。我需要最小化目标函数,即在这里将误差函数(f)最小化为零或接近零。我提到了 optimize.minimize() 而没有提到优化方法的类型。可以吗?它会给我正在寻找的正确答案吗?

【问题讨论】:

    标签: python numpy optimization lambda scipy


    【解决方案1】:

    Q1(语法):您的约束必须采用单个向量参数:

    import numpy
    import scipy.optimize as optimize
    
    #OPTIMISATION USING SCIPY
    def Obj_func(x):
        bo,ho,t1,t2=x
        f=-321226.4817 + (10400000*bo*ho**3 - 10400000*(bo - 2*t2)*(ho - 2*t1)**3)/(125 + (10400000*bo*ho**3 - 10400000*(bo - 2*t2)*(ho - 2*t1)**3)/(1563920*t1*(bo - 2*t2)))
        return f
    
    initial_guess=[2,2,0.2,0.2]
    cons = ({'type': 'eq', 'fun': lambda bhtt: (bhtt[0]*bhtt[1] - (bhtt[0] - 2*bhtt[3])*(bhtt[1] - 2*bhtt[2])-7.55)})
    bnds = ((0, None), (0, None),(0, None), (0, None)) #all four variables are positive and greater than zero
    #Always t1 and t2 should always be lesser than bo and ho
    #res=optimize.minimize(Obj_func, method='SLSQP',initial_guess, bounds=bnds,constraints=cons)
    res=optimize.minimize(Obj_func,initial_guess, bounds=bnds,constraints=cons)
    print ("Result",res)
    

    输出:

    Result      fun: -15467.04696553346
         jac: array([  165915.125     ,   147480.57421875,  1243506.8828125 ,
            -130354.05859375])
     message: 'Positive directional derivative for linesearch'
        nfev: 6
         nit: 5
        njev: 1
      status: 8
     success: False
           x: array([ 2. ,  2. ,  0.2,  0.2])
    

    Q2(数学):求解者似乎不喜欢提出的问题。通过消除等式约束和一个变量,我设法让它吐出一个解决方案。默认求解器仍然不起作用,但 COBYLA 起作用了:

    import numpy
    import scipy.optimize as optimize
    from operator import itemgetter
    
    #OPTIMISATION USING SCIPY
    def Obj_func_orig(x):
        bo,ho,t1,t2=x
        f=-321226.4817 + (10400000*bo*ho**3 - 10400000*(bo - 2*t2)*(ho - 2*t1)**3)/(125 + (10400000*bo*ho**3 - 10400000*(bo - 2*t2)*(ho - 2*t1)**3)/(1563920*t1*(bo - 2*t2)))
        return f
    
    def Obj_func(x):
        bh, h, t = x
        btht = bh - 7.55
        D = bh*h*h - btht*(h-t)*(h-t)
        f = -321226.4817 + D / (125/10400000 + D*(h-t)/(781960*t*btht))
        return f
    
    def cons(x):
        bh, h, t = x
        btht = bh - 7.55
        return (btht * h - bh * (h-t)) * (t-h)
    
    def ge(i):
        return {'type': 'ineq', 'fun': itemgetter(i)}
    
    initial_guess=[1,1,1]
    initial_guess=[64,8,0.5]
    cons = ({'type': 'ineq', 'fun': cons}, {'type': 'ineq', 'fun': Obj_func}, ge(0), ge(1), ge(2))
    res=optimize.minimize(lambda x: Obj_func(x)**2,initial_guess,constraints=cons,method='COBYLA')
    print ("Result",res)
    bh, h, t = res.x
    bo, ho, t1, t2 = bh / h, h, t/2, (bh / h - (bh - 7.55) / (h-t))/2
    print('bo, ho, t1, t2, f', bo, ho, t1, t2, Obj_func_orig([bo,ho,t1,t2]))
    

    用 OP 的初步猜测回答:

    # Result      fun: 285138.38958324661
    #    maxcv: 0.0
    #  message: 'Optimization terminated successfully.'
    #     nfev: 47
    #   status: 1
    #  success: True
    #        x: array([  6.40732657e+01,   8.29209901e+00,   6.03312595e-02])
    # bo, ho, t1, t2, f 7.72702612177 8.29209901408 0.0301656297535 0.430273240999 533.983510591
    

    请注意,这些显然是取决于初始猜测的局部最小值。例如,如果我将1,1,1 用于转换后的变量:

    # Result      fun: 5829.8452437661899
    #    maxcv: 0.0
    #  message: 'Optimization terminated successfully.'
    #     nfev: 48
    #   status: 1
    #  success: True
    #        x: array([ 4.39911932,  0.93395108,  0.89739524])
    # bo, ho, t1, t2, f 4.71022456896 0.933951079923 0.44869761948 45.4519279253 76.3534232616
    

    【讨论】:

    • 非常感谢您的回答。这里的目标函数最小化到 0 以下,即 fun:-15467.04696553346。但我想获得目标函数最小化为零而不低于零的变量。我该怎么做?
    • @PaulThomas 从理论上讲,应该可以将目标函数用作不等式约束。但是当我尝试这个时,它没有找到解决方案。有时,更好的初步猜测会有所帮助。您能否提供一个至少具有非负函数值的函数?
    • 如果不完全为零,是否可以将目标函数 (f) 值限制为接近零?或者是否可以采用 f 的绝对值,即 abs(f) 在这种情况下,最小值将为零或接近于零。实际上,我正在为这类功能寻找解决方案,这些功能既有正面的也有负面的。我认为更好的初始猜测是 [8, 8, 0.25, 0.25]
    • @PaulThomas 我或多或少地得到了它的工作,但它远非完美。看看更新的答案。
    猜你喜欢
    • 2018-05-10
    • 1970-01-01
    • 2015-05-09
    • 2021-12-06
    • 2018-05-09
    • 2014-01-03
    • 2015-02-20
    • 2016-03-16
    • 1970-01-01
    相关资源
    最近更新 更多