Противоречивый вывод из решателя CVXPY
Я знакомлюсь с CVXPY и столкнулся со странной проблемой. У меня есть следующая простая задача оптимизации игрушек:
import numpy as np
import cvxpy as cp
A=np.array([[1,0,0],[0,1,0], [0,0,1]])
y=np.array([1,1,1])
# Upper bound for the constraint term
upper=1
# Solve the optimization problem using CVXPY
x = cp.Variable(3)
objective = cp.Minimize(cp.sum_squares(x))
constraint = [cp.sum_squares(A*x - y) <= upper]
prob = cp.Problem(objective, constraint)
prob.solve()
optimal_x = x.value
print('Value of constraint at optimal x:' + str(np.linalg.norm(A*optimal_x - y)**2))
Теперь я ожидаю, что мой выходной номер будет меньше, чем upper=1
, но я получаю следующее:
Value of constraint at optimal x:3.0000000068183947
Я очень смущен тем, как это может быть правдой. Я использую функцию cp.sum_squares
неправильно? Я просто настраиваю оптимизацию неправильно? Любая помощь приветствуется!
1 ответ
Я думаю, что путаница проистекает из неправильного умножения матриц в numpy
:
>>> A * optimal_x - y
array([[-0.57735027, -1. , -1. ],
[-1. , -0.57735027, -1. ],
[-1. , -1. , -0.57735027]])
Где на самом деле то, что я думаю, вы хотите
>>> np.dot(A, optimal_x) - y
array([-0.57735027, -0.57735027, -0.57735027])
Что действительно не нарушает ограничение (в пределах ошибок округления):
>>> np.linalg.norm(np.matmul(A, optimal_x) - y) ** 2
1.000000002699704
Также см. Этот вопрос для справки по умножению матрицы на массив в numpy
,
Это действительно сбивает с толку, потому что CVXPY
объекты правильно обрабатывают *
оператор, даже с типами numpy:
>>> (A * x - y).value
array([-0.57735027, -0.57735027, -0.57735027])
Также обратите внимание, что для любого дерева выражений, которое вы строите в CVXPY
после оптимизации вы можете запросить значение этого выражения с учетом оптимизированного x
значение:
>>> cp.sum_squares(A*x - y).value
array(1.)