#python #r #cvxpy #cvx #cvxr
Вопрос:
Я использую CVXR
пакет моделирования для решения задачи выпуклой оптимизации. Я точно знаю, что проблема выпуклая и что она следует правилам DCP, но если я проверю правила DCP, используя CVXR
их, она вернется False
. Однако, если я возьму точно такую же проблему и проверю ее с помощью CVXPY
, она вернется True
(как и ожидалось)
Что здесь происходит? Я прилагаю минимальный воспроизводимый пример такого поведения в R и Python:
Код R с использованием CVXR
library(splines2)
library(CVXR)
deriv_basis = splines2::dbs(seq(0, 1, length.out=100), degree=3, intercept=T, df=30, derivs=2)
R = t(deriv_basis) %*% deriv_basis
beta_var = CVXR::::Variable(nrow(R))
q = CVXR::quad_form(beta_var, R)
CVXR::is_dcp(q)
[1] FALSE
write.table(x=R, file='R.csv'), row.names=F, sep=';')
Код на Python с использованием CVXPY
import cvxpy
import pandas as pd
R = pd.read_csv('R.csv', sep=';').values
beta_var = cvxpy.Variable(R.shape[1])
q = cvxpy.quad_form(beta_var, R)
q.is_dcp()
Out[1]: True
Может ли кто-нибудь объяснить, что здесь происходит и как это решить, чтобы я мог использовать CVXR?
Ответ №1:
Проблема заключается в отрицательном собственном значении в матрице R. Если вы исправите это, установив его, скажем, на ноль, то это удовлетворит условию dcp. Я также исправил синтаксические ошибки в коде в вопросе и удалил избыточное :: . Еще одна возможность (не показана) — использовать nearest_spd
в пакете pracma для настройки матрицы R.
library(splines2)
library(CVXR)
deriv_basis <- dbs(seq(0, 1, length.out=100), degree = 3,
intercept = TRUE, df = 30, derivs = 2)
R <- t(deriv_basis) %*% deriv_basis
e <- eigen(R)
# check decomposition
all.equal(R, e$vectors %*% diag(e$values) %*% t(e$vectors),
check.attributes = FALSE)
## [1] TRUE
e$values # note negative value
## [1] 1.095213e 08 1.095213e 08 1.056490e 07 1.055430e 07 1.052481e 07
## [6] 1.046063e 07 1.034247e 07 1.015017e 07 9.866358e 06 9.485145e 06
## [11] 8.643220e 06 8.280963e 06 7.549803e 06 6.731472e 06 5.853402e 06
## [16] 4.949804e 06 4.056714e 06 3.209045e 06 2.437320e 06 1.759963e 06
## [21] 1.214976e 06 7.785251e 05 4.590441e 05 2.428199e 05 1.107300e 05
## [26] 4.060476e 04 1.040537e 04 1.320942e 03 7.239578e-09 -5.019224e-09
# zap negative eigenvalues making them zero
R <- with(e, vectors %*% diag(pmax(values, 0)) %*% t(vectors))
beta_var <- Variable(nrow(R))
q <- quad_form(beta_var, R)
is_dcp(q)
## [1] TRUE
Комментарии:
1. Спасибо вам за ответ! И знаете ли вы, почему существует разница в правилах DCP между R и python?
2. Нельзя предположить, что правила DCP ведут себя по-другому. Вполне возможно, что программное обеспечение Python создает матрицу PSD R. Проверьте собственные значения на стороне Python, как мы сделали в ответе на стороне R.
Ответ №2:
cvxpy
должно дать те же результаты, CVXR
что и подразумевается Г. Гротендиком, поскольку правила DCP одинаковы. Кажется, что-то сломалось в последних версиях cvxpy
. Я открыл проблему на cvxpy github.