Оптимизировать нескалярную функцию с ограничением неравенства - PullRequest
0 голосов
/ 13 июня 2019

Я ищу метод оптимизации в scipy, который позволил бы мне минимизировать объектную функцию f (x, y) (возвращает вектор) с учетом ограничения g (x, y) <0.1 и дополнительных границ для x и y. </p>

Я попытался решить свою проблему с помощью scipy.optimize.least_squares, scipy.optimize.leastsq и scipy.optimize.minimize.Проблема состоит в том, что leastsq и less_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

Я сделал это с помощью метода less_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

Чтобы реализовать ограничение, я протестировал функцию минимизации Сципи

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

Но здесь я не могу найти способ разрешитьmy_cost и f_noise - массивы 3x1.

За любую помощь я очень благодарен!Приветствия за ваше время!

1 Ответ

0 голосов
/ 14 июня 2019

Согласно документам , целевая функция должна возвращать число с плавающей запятой при использовании scipy.optimize.minimize, тогда как с scipy.optimize.least_squares вы не можете использовать ограничения. В этом случае вы должны знать о своей цели минимизации. Минимизация разностного вектора (например, f-f_noise) эквивалентна минимизации разностей элементов и, следовательно, их суммы. Поэтому практическим решением было бы минимизировать определенную p-норму ваших f(x,y) и g(x). Я предлагаю квадрат L2-норма , поскольку он очень похож на то, что вы пытаетесь выполнить в своей функции затрат, и он прост и стабилен (по сравнению с другими нормами).

enter image description here

Вы можете усреднить норму и получить Среднее квадратичное отклонение (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)
...