Search code examples
pythoncvxpyconvex-optimization

Using cvxpy to solve a lasso like problem


It's not entirely lasso because I add an extra constraint but I'm not sure how I'm supposed to solve a problem like the following using cvxpy

import cvxpy as cp
import numpy as np

A = np.random.rand(5000,1000)
v0 = np.random.rand(1000,1)
v = cp.Variable(v0.shape)
iota = np.ones(v0.shape)

lam = 1

objective = cp.Minimize( (A@(v-v0)).T@(A@(v-v0)) + lam * cp.abs(v).T @ iota )
constraints = [v >= 0]

prob = cp.Problem(objective, constraints)
res = prob.solve()

I tried various versions of this but this is the one that most clearly shows what I'm trying to do. I get the error:

DCPError: Problem does not follow DCP rules. Specifically: The objective is not DCP. Its following subexpressions are not: ....

And then an error I don't undeerstand haha.


Solution

  • CVXPY is a modeling language for convex optimization. Therefore, there is a set of rules your problem must follow to ensure your problem is convex indeed. These are what cvxpy refers to DCP: Disciplined Convex Programming. As the error suggests, your objective is not DCP.

    To be more precise, the problem is in the objective (A@(v-v0)).T@(A@(v-v0)): cvxpy don't know it is indeed convex (from program point of view, it's just few multiplications).

    To ensure your problem is DCP, it's best to use cvxpy atomic functions. Essentially you are modeling x^T * x (if x=A@(v-v0)), which is the squares of norm 2 of a vector. cp.norm2 is the way to ensure cvxpy will know the problem is convex.

    change the line of the objective function to:

    objective = cp.Minimize(cp.norm2(A @ (v - v0)) ** 2 + lam * cp.abs(v).T @ iota)
    

    and it works.

    (Also take a look at cvxpy example of lasso regression)