【问题标题】:Optimize non-scalar function with inequality constraint and bounds使用不等式约束和边界优化非标量函数
【发布时间】:2023-04-03 20:47:02
【问题描述】:

我正在 scipy 中寻找一种优化方法,它允许我最小化对象函数 f(x,y)(返回向量),受约束 g(x,y)

我尝试使用 scipy.optimize.least_squares、scipy.optimize.leastsq 和 scipy.optimize.minimize 来解决我的问题。问题是 minimumsq 和 least_squares 允许对象函数是非标量的,但不给我实现约束的可能性(仅限边界)。另一方面,minimize 给了我实现约束和边界的可能性,但是 f(x,y) 必须返回一个标量。因此,我正在寻找一种将两者结合起来的解决方案。有谁知道这样的事情是否存在?

我要最小化的函数是

def my_cost(p,f_noise):
    x,y = p[0], p[1]
    f = #some function that returns a 3x1 array
    return (f - fnoise)**2

我用最小二乘法做到了这一点。

opti.least_squares(my_cost, p0[:], args = (f_noise,),gtol=1e-2, bounds=bounds)

但是在这里我有一个问题,我无法约束 p 中的变量。我需要约束 p 以使其满足

def constraint(p)
    x = p[0]
    return fy(x) - y <= 0.1 #variable y therefore becomes a function of variable x

为了实现约束,我测试了 scipy 的最小化函数

opti.minimize(my_cost, p0[:], args = (f_noise,), bounds = bounds, constraints={'type': 'eq', 'fun': constraint})

但在这里我似乎找不到让 my_cost 和 f_noise 成为 3x1 数组的方法。

对于任何帮助,我都非常感激! 为你的时间干杯!

【问题讨论】:

    标签: python optimization scipy least-squares scipy-optimize-minimize


    【解决方案1】:

    根据docs,使用scipy.optimize.minimize 时目标函数必须返回一个浮点数,而使用scipy.optimize.least_squares,则不能使用约束。 在这种情况下,您必须了解您的最小化目的。最小化差异向量(如f-f_noise)等效于最小化元素差异,从而最小化它们的总和。因此,一个实用的解决方案是最小化您的f(x,y)g(x) 的定义 p 范数。我建议使用正方形 L2-norm,因为它与您在成本函数中尝试的非常相似,并且简单且稳定(与其他规范相比)。

    您可以平均标准并获得Mean Squared Error (MSE)

    应用前面的概念,可以得到如下代码:

    import numpy as np 
    from scipy.optimize import minimize
    
    # define fy
    def fy(x):
        return x**2 * np.array([[.1],[.2],[.3]])  # some function that returns a 3x1 array
    
    # objective func
    def f(p, f_noise):
        x, y = p[0], p[1]
        f    = x * y * np.array([[1],[2],[3]])    # some function that returns a 3x1 array
        return np.linalg.norm(f - f_noise, 2)**2
    
    # constraint
    def g(p):
        x         = p[0]
        diff_norm = np.linalg.norm(fy(x) - y) 
        return threshold - diff_norm 
    
    # init 
    f_noise   = np.array([[.1],[.2],[.3]])
    p0        = np.array([1, 0.5])
    bounds    = ((0,2),(0,2))
    y         = np.array([[.9],[.7],[.2]])
    threshold = 0.1  # make sure to choose an adequate threshold
    
    # minimize
    result  =  minimize(f, p0,
                        args        = (f_noise,), 
                        bounds      = bounds, 
                        constraints = {'type': 'ineq', 'fun': g})
    
    # print result
    print(result)
    

    【讨论】:

    • 感谢您非常有帮助和快速的回​​答,SuperKogito!棒极了!我会测试它并稍后回复,这是否解决了我的问题。
    • 非常感谢,SuperKogito。尽管我仍在运行一些测试,但这似乎仍然有效。我对这个解决方案有一个问题:约束是通过阈值选择的。这不会将找到的解决方案减少到阈值 = diff_norm 的最佳值,而不是 diffnorm
    • 这更多地取决于您的问题的性质。您可以决定哪种约束类型(相等或不等)在您的情况下更有效。我认为不等式可能更快,因为与找到等于阈值的值相比,找到低于阈值的值通常更容易。
    • 是的,完全正确。我认为它会更快。我想将最小化限制在 g(x,y)
    • 在我的示例中,我使用了不等式约束。我在constraints = {'type': 'ineq', 'fun': g} 这一行中定义了它。因此,最小化正在寻找解决方案,同时确保约束的返回为正:g(p) &gt;= 0 -&gt; threshold - diff_norm &gt;= 0 -&gt; threshold &gt;= diff_norm。请阅读约束部分here并参考this
    猜你喜欢
    • 2018-03-15
    • 2020-04-12
    • 2023-01-19
    • 2019-05-23
    • 2015-08-10
    • 2020-03-22
    • 1970-01-01
    • 1970-01-01
    • 2023-03-16
    相关资源
    最近更新 更多