使用不等式约束和边界优化非标量函数

时间:2019-06-13 11:12:37

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

我正在寻找scipy中的一种优化方法,该方法允许我在约束g(x,y)<0.1以及x和y的附加边界的情况下最小化目标函数f(x,y)(返回向量)。 / p>

我尝试使用scipy.optimize.least_squares,scipy.optimize.leastsq和scipy.optimize.minimize解决问题。问题是minimumsq和minimum_squares允许对象函数是非标量的,但没有给我实现约束的可能性(仅边界)。另一方面,最小化使我可以同时实现约束和界限,但是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

我用minimum_squares方法做到了。

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数组的方法。

对于任何帮助,我非常感谢! 为您的时间加油!

1 个答案:

答案 0 :(得分:0)

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

enter image description here

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

enter image description here

通过应用前面的概念,您将获得以下代码:

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)