使用 Scipy 在 Python 中进行约束优化

Posted

技术标签:

【中文标题】使用 Scipy 在 Python 中进行约束优化【英文标题】:Constrained Optimization in Python using Scipy 【发布时间】:2022-01-22 23:31:21 【问题描述】:

我有一个函数 f : (a.y1 + b.y2 + c.y3 + d.y4 + e.y5 + f.y6) 我需要最小化 root_mean_squared_error(f)。线性约束是:a+b+c+d+e+f = 1。边界是 a,b,c... 中的每一个都应该在 [0,1] 之间。我试图找出 a、b、c、d、e 和 f 的优化值。我正在使用 Scipy,但我觉得我无法将边界和约束正确地放在“最小化”代码中,如下所示:(y0 是给定的原始测试值(比如说))。

    import numpy as np
    from scipy.optimize import minimize
    from scipy.optimize import LinearConstraint
    def root_mean_squared_error(y1, y2):
        squared_difference = (y1 - y2)**2
        mean_squared = np.mean(squared_difference)
    return np.sqrt(mean_squared)

    def rms(params):
         a, b, c , d , e, f = params
         yF = sum(a*y1 + b*y2 + c*y3 + d*y_4 + e*y5 + f*y6)
         return root_mean_squared_error(y0, yF)
    initial_guess = [0.2, 0.1, 0.2, 0.05, 0.3, 0.15]
    constraint = LinearConstraint([1,1,1,1,1,1],1,1)
    bound = ([0, 1],[0, 1],[0, 1],[0, 1],[0, 1],[0, 1])
    res = minimize(rms, initial_guess, method='nelder-mead', bounds = bound,constraints = constraint)
    print(res.x)

我得到的值非常小,加起来不等于一,例如:

[1.28941447e-04 1.90583408e-04 8.50096927e-05 2.08311702e-04 1.17829816e-04 0.00000000e+00]

这是使用 scipy 线性约束和绑定的正确方法吗

【问题讨论】:

【参考方案1】:

约束(仅适用于 COBYLA、SLSQP 和 trust-constr)。

因此,您可能需要将您的 method=nelder-mead 更改为其中之一,否则约束将被忽略。

由于这是一个等式约束,您必须使用 method='SLSQP'method='trust-constr'

【讨论】:

感谢您的提示。我尝试使用 SLSQP,将等式约束以字典的形式,但它只是将初始/起始参数作为最终结果本身返回给我。 'trust-constr' 给我的结果与 nelder-mead 相似,但加起来不为零。 只需在原始代码中使用约束LinearConstraint 对不起,我没有关注。您是在问我是否应该按原样使用约束而不将其变成字典?如果是这种情况,那么是的,我这样做了,它给出了相同的结果,即起始参数。 在你的代码中你使用的是constraint = LinearConstraint([1,1,1,1,1,1],1,1),这是正确的,不知道为什么它给出了你可能需要提供yi的示例数据的起始参数

以上是关于使用 Scipy 在 Python 中进行约束优化的主要内容,如果未能解决你的问题,请参考以下文章

如何在有约束的 scipy 中使用最小化函数

Scipy 最小化约束函数

当我尝试使用 for 循环设置约束时,Scipy 优化未运行

Python数模笔记-Scipy库线性规划问题

python非线性规划用啥模块

Scipy优化算法--scipy.optimize.fmin_tnc()/minimize()