当我尝试使用 for 循环设置约束时,Scipy 优化未运行
Posted
技术标签:
【中文标题】当我尝试使用 for 循环设置约束时,Scipy 优化未运行【英文标题】:Scipy Optimization Not Running when I try to set constraints using a for loop 【发布时间】:2018-01-11 11:33:45 【问题描述】:我试图最小化目标函数,同时使用 for 循环设置约束,使得 x1 = x2 = ... xn。但是,优化似乎不起作用。 IE。结束 x 仍然等于初始 x。我收到一条错误消息“LSQ 子问题中的奇异矩阵 C”。
covariance_matrix = np.matrix([[0.159775519, 0.022286316, 0.00137635, -0.001861736],
[0.022286316, 0.180593862, -5.5578e-05, 0.00451056],
[0.00137635, -5.5578e-05, 0.053093075, 0.02240866],
[-0.001861736, 0.00451056, 0.02240866, 0.053778594]])
x0 = np.matrix([0.2,0.2,0.3,0.4])
fun = lambda x: x.dot(covariance_matrix).dot(x.transpose())
cons = np.array([])
for i in range(0,x0.size-1):
con = 'type': 'eq', 'fun': lambda x: x[i] - x[i+1]
cons = np.append(cons, con)
con = 'type': 'eq', 'fun': lambda x: sum(x)-1
cons = np.append(cons, con)
solution = minimize(fun,x0,method='SLSQP',constraints = cons)
solution message: Singular matrix C in LSQ subproblem
solution status: 6
solution success: False
但是如果我一个一个地附加约束,那么它就可以完美地工作,这意味着结果给了我 x1 = x2 = x3 = x4
con1 = 'type': 'eq', 'fun': lambda x: sum(x)-1
con2 = 'type': 'eq', 'fun': lambda x: x[1]-x[0]
con3 = 'type': 'eq', 'fun': lambda x: x[2]-x[1]
con4 = 'type': 'eq', 'fun': lambda x: x[3]-x[2]
cons = np.append(cons, con1)
cons = np.append(cons, con2)
cons = np.append(cons, con3)
cons = np.append(cons, con4)
solution message: Optimization terminated successfully.
solution status: 0
solution success: True
【问题讨论】:
"...优化似乎不起作用。即结束x仍然等于初始x。"无需猜测它“没有'似乎不起作用'。solution
对象告诉通过将 solution.success
设置为 False 不起作用。原因的简短描述在solution.message
中。致电minimize()
后,请务必检查solution.success
。您能否在调用minimize()
后编辑问题以显示solution.success
、solution.status
和solution.message
?
谢谢沃伦!我已经编辑了最初的问题。看来我遇到了“LSQ 子问题中的奇异矩阵 C”问题。你知道这是从哪里来的吗?
看起来该消息是从底层 Fortran 求解器的源代码中复制的。不幸的是,我在minimize
或fmin_slsqp
的文档字符串中没有看到“矩阵C”的描述,所以有人必须深入研究Fortran 代码(至少是Fortran 代码中的cmets)才能弄清楚C是什么。 scipy中的代码是slsqp_optmz.f.
不过,我要补充一点,你的等式约束唯一地确定了解决方案——在你的问题中没有什么可以优化的。
沃伦,你能详细说明一下吗?我认为设置是最小化目标函数。我的主要问题是,如果我一一附加这些约束,那么它就可以工作。但如果我使用循环,则不会。
【参考方案1】:
(注意:虽然细节不同,但这个问题和Scipy.optimize.minimize SLSQP with linear constraints fails的问题差不多)
你的循环是
for i in range(0,x0.size-1):
con = 'type': 'eq', 'fun': lambda x: x[i] - x[i+1]
cons = np.append(cons, con)
问题是在 lambda 表达式中使用了i
。 Python closures are "late binding"。这意味着调用函数时使用的i
的值与创建函数时的i
的值不同。在循环之后,i
的值为 2,因此循环中创建的所有函数计算的表达式为 x[2] - x[3]
。 (这也解释了错误消息中提到的“奇异矩阵 C”。)
解决此问题的一种方法是将i
设为默认值为当前i
的lambda 表达式的参数:
con = 'type': 'eq', 'fun': lambda x, i=i: x[i] - x[i+1]
【讨论】:
完美答案! 我非常感谢您的回答。我是 SciPy 的新手,对此我很头疼!非常感谢@Warren @dickli2119 您可以通过勾选箭头来接受答案。以上是关于当我尝试使用 for 循环设置约束时,Scipy 优化未运行的主要内容,如果未能解决你的问题,请参考以下文章