为什么在scipy.optimize.minimize中约束失败?

huangapple go评论65阅读模式
英文:

Why do constraints fail in scipy.optimize.minimize

问题

def get_cons(self, ub, lb):
    cons = []
    for i in range(len(ub)):
        cons.append({'type': 'ineq', 'fun': lambda x0: ub[i] - x0[i]})
        cons.append({'type': 'ineq', 'fun': lambda x0: x0[i] - lb[i]})
    return cons

ub = [1, 3, 1, 1]
lb = [0, 0, 0, 0]
cons = self.get_cons(self.ub, self.lb)
res = minimize(fun, x0[:, i], method='SLSQP', constraints=cons)

Here, fun is a custom loss function. The initial parameters are [0.08024884, 0.14003958, 0.0786131, 0.00157402]. You expect all parameters to be greater than 0, but after optimization, the parameters are [-0.45684621, 0.02531972, -0.10755587, 0.2108312].

The constraints in your code ensure that ub[i] - x0[i] >= 0 and x0[i] - lb[i] >= 0 for all i in the range of your parameters. Since the optimized parameters violate these constraints (some are negative), it indicates that the constraint is not satisfied.

英文:
    def get_cons(self, ub, lb):
        cons = []
        for i in range(len(ub)):
            cons.append({'type':'ineq','fun':lambda x0:ub[i]-x0[i]})
            cons.append({'type':'ineq','fun':lambda x0:x0[i]-lb[i]})
        return cons
    ub = [1,3,1,1]
    lb = [0,0,0,0]
    cons = self.get_cons(self.ub, self.lb)
    res = minimize(fun, x0[:,i], method='SLSQP', constraints=cons)

Here fun is custom loss function
initial parameter is [0.08024884 0.14003958 0.0786131 0.00157402]. I expect all parameter>0,but after optimize parmeter is [-0.45684621 0.02531972 -0.10755587 0.2108312].

Whether this constraint fails?

答案1

得分: 1

不需要使用通用约束来对变量添加简单的界限。相反,通过minimizebound参数传递变量界限:

bounds = [(l, u) for (l, u) in zip(lb, ub)]

res = minimize(fun, x0[:, i], bounds=bounds, method="SLSQP")

然而,如果你真的想将界限作为通用约束传递,你需要捕获循环变量i的值:

for i in range(len(ub)):
    cons.append({'type': 'ineq', 'fun': lambda x0, i=i: ub[i] - x0[i]})
    cons.append({'type': 'ineq', 'fun': lambda x0, i=i: x0[i] - lb[i]})
return cons

否则,每个约束都会共享最后一次循环迭代的i的值,详细信息请参见这里

英文:

There's no need to use generic constraints for adding simple bounds on the variables. Instead, pass the variable bounds via minimize's bound argument:

bounds = [(l, u) for (l, u) in zip(lb, ub)]

res = minimize(fun, x0[:, i], bounds=bounds, method="SLSQP") 

However, if you really want to pass the bounds as generic constraints, you need to capture the value of the loop variable i:

for i in range(len(ub)):
    cons.append({'type':'ineq','fun': lambda x0, i=i: ub[i]-x0[i]})
    cons.append({'type':'ineq','fun': lambda x0: i=i: x0[i]-lb[i]})
return cons

Otherwise, each constraint shares the value of i of the last loop iteration, see here for further details.

huangapple
  • 本文由 发表于 2023年1月8日 23:14:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/75048895.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定