英文:
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
不需要使用通用约束来对变量添加简单的界限。相反,通过minimize
的bound
参数传递变量界限:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论