#python #numpy #optimization #scipy #scipy-optimize
#python #numpy #оптимизация #scipy #scipy-оптимизировать
Вопрос:
У меня проблема оптимизации, когда я пытаюсь найти массив, который должен оптимизировать две функции одновременно.
В минимальном примере ниже у меня есть два известных массива w
x
и неизвестный массив y
. Я инициализирую массив y
, содержащий только 1s.
Затем я указываю функцию np.sqrt(np.sum((x-np.array)**2)
и хочу найти массив y
, в котором
np.sqrt(np.sum((x-y)**2)
подходы 5
np.sqrt(np.sum((w-y)**2)
подходы 8
Приведенный ниже код можно использовать для успешной оптимизации y
в отношении одного массива, но я хотел бы найти решение, которое оптимизирует y
в отношении обоих x
и y
одновременно, но я не уверен, как указать два ограничения.
y
должно состоять только из значений, превышающих 0.
Есть идеи о том, как это сделать?
w = np.array([6, 3, 1, 0, 2])
x = np.array([3, 4, 5, 6, 7])
y = np.array([1, 1, 1, 1, 1])
def func(x, y):
z = np.sqrt(np.sum((x-y)**2)) - 5
return np.zeros(x.shape[0],) z
r = opt.root(func, x0=y, method='hybr')
print(r.x)
# array([1.97522498 3.47287981 5.1943792 2.10120135 4.09593969])
print(np.sqrt(np.sum((x-r.x)**2)))
# 5.0
Ответ №1:
Одним из вариантов является использование scipy.optimize.minimize
вместо root
, здесь у вас есть несколько параметров решателя, и некоторые из них (ie SLSQP
) позволяют указать несколько ограничений. Обратите внимание, что я изменил имена переменных, чтобы это x
был массив, который вы хотите оптимизировать, y
и z
определить ограничения.
from scipy.optimize import minimize
import numpy as np
x0 = np.array([1, 1, 1, 1, 1])
y = np.array([6, 3, 1, 0, 2])
z = np.array([3, 4, 5, 6, 7])
constraint_x = dict(type='ineq',
fun=lambda x: x) # fulfilled if > 0
constraint_y = dict(type='eq',
fun=lambda x: np.linalg.norm(x-y) - 5) # fulfilled if == 0
constraint_z = dict(type='eq',
fun=lambda x: np.linalg.norm(x-z) - 8) # fulfilled if == 0
res = minimize(fun=lambda x: np.linalg.norm(x), constraints=[constraint_y, constraint_z], x0=x0,
method='SLSQP', options=dict(ftol=1e-8)) # default 1e-6
print(res.x) # [1.55517124 1.44981672 1.46921122 1.61335466 2.13174483]
print(np.linalg.norm(res.x-y)) # 5.00000000137866
print(np.linalg.norm(res.x-z)) # 8.000000000930026
Это минимизатор, поэтому, помимо ограничений, он также требует минимизации функции, я выбрал только норму y
, но установка функции на константу (т. Е. лямбда x: 1) также сработала бы.
Также обратите внимание, что ограничения не выполняются в точности, вы можете повысить точность, установив необязательный аргумент ftol
на меньшее значение, т.Е. 1e-10
.
Для получения дополнительной информации см. Также Документацию и соответствующие разделы для каждого решателя.