<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>CVXR package on R Views</title>
    <link>https://rviews.rstudio.com/tags/cvxr-package/</link>
    <description>Recent content in CVXR package on R Views</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    <lastBuildDate>Fri, 20 Jul 2018 00:00:00 +0000</lastBuildDate>
    <atom:link href="https://rviews.rstudio.com/tags/cvxr-package/" rel="self" type="application/rss+xml" />
    
    
    
    
    <item>
      <title>CVXR: A Direct Standardization Example</title>
      <link>https://rviews.rstudio.com/2018/07/20/cvxr-a-direct-standardization-example/</link>
      <pubDate>Fri, 20 Jul 2018 00:00:00 +0000</pubDate>
      
      <guid>https://rviews.rstudio.com/2018/07/20/cvxr-a-direct-standardization-example/</guid>
      <description>
        


&lt;p&gt;In our &lt;a href=&#34;https://rviews.rstudio.com/2017/11/27/introduction-to-cvxr/&#34;&gt;first blog post&lt;/a&gt;, we introduced &lt;code&gt;CVXR&lt;/code&gt;, an R package for disciplined convex optimization, and showed how to model and solve a non-negative least squares problem using its interface. This time, we will tackle a non-parametric estimation example, which features new atoms as well as more complex constraints.&lt;/p&gt;
&lt;div id=&#34;direct-standardization&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Direct Standardization&lt;/h2&gt;
&lt;p&gt;Consider a set of observations &lt;span class=&#34;math inline&#34;&gt;\((x_i,y_i)\)&lt;/span&gt; drawn non-uniformly from an unknown distribution. We know the expected value of the columns of &lt;span class=&#34;math inline&#34;&gt;\(X\)&lt;/span&gt;, denoted by &lt;span class=&#34;math inline&#34;&gt;\(b \in {\mathbf R}^n\)&lt;/span&gt;, and want to estimate the true distribution of &lt;span class=&#34;math inline&#34;&gt;\(y\)&lt;/span&gt;. This situation may arise, for instance, if we wish to analyze the health of a population based on a sample skewed toward young males, knowing the average population-level sex, age, etc.&lt;/p&gt;
&lt;p&gt;A naive approach would be to simply take the empirical distribution that places equal probability &lt;span class=&#34;math inline&#34;&gt;\(1/m\)&lt;/span&gt; on each &lt;span class=&#34;math inline&#34;&gt;\(y_i\)&lt;/span&gt;. However, this is not a good estimation strategy when our sample is unbalanced. Instead, we will use the method of &lt;strong&gt;direct standardization&lt;/strong&gt; (Fleiss, Levin, and Paik 2003, 19.5): we solve for weights &lt;span class=&#34;math inline&#34;&gt;\(w \in {\mathbf R}^m\)&lt;/span&gt; of a weighted empirical distribution, &lt;span class=&#34;math inline&#34;&gt;\(y = y_i\)&lt;/span&gt; with probability &lt;span class=&#34;math inline&#34;&gt;\(w_i\)&lt;/span&gt;, which rectifies the skewness of the sample. This can be posed as the convex optimization problem&lt;/p&gt;
&lt;p&gt;&lt;span class=&#34;math display&#34;&gt;\[
    \begin{array}{ll} \underset{w}{\mbox{maximize}} &amp;amp; \sum_{i=1}^m -w_i\log w_i \\
    \mbox{subject to} &amp;amp; w \geq 0, \quad \sum_{i=1}^m w_i = 1,\quad X^Tw = b.
    \end{array}
\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Our objective is the total entropy, which is concave on &lt;span class=&#34;math inline&#34;&gt;\({\mathbf R}_+^m\)&lt;/span&gt;. The constraints ensure &lt;span class=&#34;math inline&#34;&gt;\(w\)&lt;/span&gt; is a probability vector that induces our known expectations over the columns of &lt;span class=&#34;math inline&#34;&gt;\(X\)&lt;/span&gt;, i.e., &lt;span class=&#34;math inline&#34;&gt;\(\sum_{i=1}^m w_iX_{ij} = b_j\)&lt;/span&gt; for &lt;span class=&#34;math inline&#34;&gt;\(j = 1,\ldots,n\)&lt;/span&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;an-example-with-simulated-data&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;An Example with Simulated Data&lt;/h2&gt;
&lt;p&gt;As an example, we generate &lt;span class=&#34;math inline&#34;&gt;\(m = 1000\)&lt;/span&gt; data points &lt;span class=&#34;math inline&#34;&gt;\(x_{i,1} \sim \mbox{Bernoulli}(0.5)\)&lt;/span&gt;, &lt;span class=&#34;math inline&#34;&gt;\(x_{i,2} \sim \mbox{Uniform}(10,60)\)&lt;/span&gt;, and &lt;span class=&#34;math inline&#34;&gt;\(y_i \sim N(5x_{i,1} + 0.1x_{i,2},1)\)&lt;/span&gt;. We calculate &lt;span class=&#34;math inline&#34;&gt;\(b_j\)&lt;/span&gt; to be the mean over &lt;span class=&#34;math inline&#34;&gt;\(x_{.,j}\)&lt;/span&gt; for &lt;span class=&#34;math inline&#34;&gt;\(j = 1,2\)&lt;/span&gt;. Then we construct a skewed sample of &lt;span class=&#34;math inline&#34;&gt;\(m = 100\)&lt;/span&gt; points that over-represent small values of &lt;span class=&#34;math inline&#34;&gt;\(y_i\)&lt;/span&gt;, thus biasing its distribution downwards.&lt;/p&gt;
&lt;p&gt;Using &lt;code&gt;CVXR&lt;/code&gt;, we construct the direct standardization problem. We first define the variable &lt;span class=&#34;math inline&#34;&gt;\(w\)&lt;/span&gt;.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;w &amp;lt;- Variable(m)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then, we form the objective function by combining &lt;code&gt;CVXR&lt;/code&gt;’s library of operators and atoms.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;objective &amp;lt;- Maximize(sum(entr(w)))&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here, &lt;code&gt;entr&lt;/code&gt; is the element-wise entropy atom; the S4 object &lt;code&gt;entr(w)&lt;/code&gt; represents an &lt;span class=&#34;math inline&#34;&gt;\(m\)&lt;/span&gt;-dimensional vector with entries &lt;span class=&#34;math inline&#34;&gt;\(-w_i\log(w_i)\)&lt;/span&gt; for &lt;span class=&#34;math inline&#34;&gt;\(i=1,\ldots,m\)&lt;/span&gt;. The &lt;code&gt;sum&lt;/code&gt; operator acts exactly as expected, forming an expression that is the sum of the entries in this vector. (For a full list of atoms, see the &lt;a href=&#34;http://cvxr.rbind.io/post/cvxr_functions/&#34;&gt;function reference&lt;/a&gt; page).&lt;/p&gt;
&lt;p&gt;Our next step is to generate the list of constraints. Note that, by default, the relational operators apply over all entries in a vector or matrix.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;constraints &amp;lt;- list(w &amp;gt;= 0, sum(w) == 1, t(X) %*% w == b)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Finally, we are ready to formulate and solve the problem.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;prob &amp;lt;- Problem(objective, constraints)
result &amp;lt;- solve(prob)
weights &amp;lt;- result$getValue(w)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Using our optimal &lt;code&gt;weights&lt;/code&gt;, we can then re-weight our skewed sample and compare it to the population distribution. Below, we plot the density functions using linear approximations for the range of &lt;span class=&#34;math inline&#34;&gt;\(y\)&lt;/span&gt;.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;## Approximate density functions
dens1 &amp;lt;- density(ypop)
dens2 &amp;lt;- density(y)
dens3 &amp;lt;- density(y, weights = weights)
yrange &amp;lt;- seq(-3, 15, 0.01)
d &amp;lt;- data.frame(x = yrange,
                True = approx(x = dens1$x, y = dens1$y, xout = yrange)$y,
                Sample = approx(x = dens2$x, y = dens2$y, xout = yrange)$y,
                Weighted = approx(x = dens3$x, y = dens3$y, xout = yrange)$y)

## Plot probability distribution functions
plot.data &amp;lt;- gather(data = d, key = &amp;quot;Type&amp;quot;, value = &amp;quot;Estimate&amp;quot;, True, Sample, Weighted,
                    factor_key = TRUE)
ggplot(plot.data) +
    geom_line(mapping = aes(x = x, y = Estimate, color = Type)) +
    theme(legend.position = &amp;quot;top&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## Warning: Removed 300 rows containing missing values (geom_path).&lt;/code&gt;&lt;/pre&gt;
&lt;div class=&#34;figure&#34;&gt;&lt;span id=&#34;fig:unnamed-chunk-6&#34;&gt;&lt;/span&gt;
&lt;img src=&#34;/post/2018-07-20-cvxr-a-direct-standardization-example_files/figure-html/unnamed-chunk-6-1.png&#34; alt=&#34;Probability distribution functions: population, skewed sample and reweighted sample&#34; width=&#34;672&#34; /&gt;
&lt;p class=&#34;caption&#34;&gt;
Figure 1: Probability distribution functions: population, skewed sample and reweighted sample
&lt;/p&gt;
&lt;/div&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;## Return the cumulative distribution function
get_cdf &amp;lt;- function(data, probs, color = &amp;#39;k&amp;#39;) {
    if(missing(probs))
        probs &amp;lt;- rep(1.0/length(data), length(data))
    distro &amp;lt;- cbind(data, probs)
    dsort &amp;lt;- distro[order(distro[,1]),]
    ecdf &amp;lt;- base::cumsum(dsort[,2])
    cbind(dsort[,1], ecdf)
}

## Plot cumulative distribution functions
d1 &amp;lt;- data.frame(&amp;quot;True&amp;quot;, get_cdf(ypop))
d2 &amp;lt;- data.frame(&amp;quot;Sample&amp;quot;, get_cdf(y))
d3 &amp;lt;- data.frame(&amp;quot;Weighted&amp;quot;, get_cdf(y, weights))

names(d1) &amp;lt;- names(d2) &amp;lt;- names(d3) &amp;lt;- c(&amp;quot;Type&amp;quot;, &amp;quot;x&amp;quot;, &amp;quot;Estimate&amp;quot;)
plot.data &amp;lt;- rbind(d1, d2, d3)

ggplot(plot.data) +
    geom_line(mapping = aes(x = x, y = Estimate, color = Type)) +
    theme(legend.position = &amp;quot;top&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;div class=&#34;figure&#34;&gt;&lt;span id=&#34;fig:unnamed-chunk-7&#34;&gt;&lt;/span&gt;
&lt;img src=&#34;/post/2018-07-20-cvxr-a-direct-standardization-example_files/figure-html/unnamed-chunk-7-1.png&#34; alt=&#34;Cumulative distribution functions: population, skewed sample and reweighted sample&#34; width=&#34;672&#34; /&gt;
&lt;p class=&#34;caption&#34;&gt;
Figure 2: Cumulative distribution functions: population, skewed sample and reweighted sample
&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;As is clear from the plots, the sample probability distribution peaks around &lt;span class=&#34;math inline&#34;&gt;\(y = 2.0\)&lt;/span&gt;, and its cumulative distribution is shifted left from the population’s curve, a result of the downward bias in our sampled &lt;span class=&#34;math inline&#34;&gt;\(y_i\)&lt;/span&gt;. However, with the direct standardization weights, the new empirical distribution cleaves much closer to the true distribution shown in red.&lt;/p&gt;
&lt;p&gt;We hope you’ve enjoyed this demonstration of &lt;code&gt;CVXR&lt;/code&gt;. For more examples, check out our &lt;a href=&#34;http://cvxr.rbind.io&#34;&gt;official site&lt;/a&gt; and recent presentation &lt;a href=&#34;https://www.youtube.com/watch?v=MyglbtnmQ8A&#34;&gt;“Disciplined Convex Optimization with CVXR”&lt;/a&gt; at useR! 2018.&lt;/p&gt;
&lt;/div&gt;

        &lt;script&gt;window.location.href=&#39;https://rviews.rstudio.com/2018/07/20/cvxr-a-direct-standardization-example/&#39;;&lt;/script&gt;
      </description>
    </item>
    
    <item>
      <title>Solver Interfaces in CVXR</title>
      <link>https://rviews.rstudio.com/2018/07/09/solver-interfaces-in-cvxr/</link>
      <pubDate>Mon, 09 Jul 2018 00:00:00 +0000</pubDate>
      
      <guid>https://rviews.rstudio.com/2018/07/09/solver-interfaces-in-cvxr/</guid>
      <description>
        

&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;

&lt;p&gt;In our &lt;a href=&#34;https://rviews.rstudio.com/2017/11/27/introduction-to-cvxr/&#34;&gt;previous blog
post&lt;/a&gt;, we
introduced &lt;code&gt;CVXR&lt;/code&gt;, an R package for disciplined convex
optimization. The package allows one to describe an optimization
problem with &lt;a href=&#34;http://dcp.stanford.edu&#34;&gt;Disciplined Convex Programming&lt;/a&gt;
rules using high level mathematical syntax. Passing this problem
definition along (with a list of constraints, if any) to the &lt;code&gt;solve&lt;/code&gt;
function transforms it into a form that can be handed off to
a solver. The default installation of &lt;code&gt;CVXR&lt;/code&gt; comes with two (imported)
open source solvers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/embotech/ecos&#34;&gt;ECOS&lt;/a&gt; and its mixed integer
cousin &lt;code&gt;ECOS_BB&lt;/code&gt; via the CRAN package
&lt;a href=&#34;https://cloud.r-project.org/package=ECOSolveR&#34;&gt;ECOSolveR&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/cvxgrp/scs&#34;&gt;SCS&lt;/a&gt; via the CRAN package
&lt;a href=&#34;https://cloud.r-project.org/package=scs&#34;&gt;scs&lt;/a&gt;.
&lt;br /&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;CVXR&lt;/code&gt; (version 0.99) can also make use of several other open source
solvers implemented in R packages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The linear and mixed integer programming package
&lt;a href=&#34;http://lpsolve.sourceforge.net/5.5/&#34;&gt;&lt;code&gt;lpSolve&lt;/code&gt;&lt;/a&gt; via the
&lt;a href=&#34;https://cloud.r-project.org/package=lpSolveAPI&#34;&gt;&lt;code&gt;lpSolveAPI&lt;/code&gt;&lt;/a&gt; package&lt;/li&gt;
&lt;li&gt;The linear and mixed integer programming package &lt;a href=&#34;https://www.gnu.org/software/glpk/&#34;&gt;&lt;code&gt;GLPK&lt;/code&gt;&lt;/a&gt; via the
&lt;a href=&#34;https://cloud.r-project.org/package=Rglpk&#34;&gt;&lt;code&gt;Rglpk&lt;/code&gt;&lt;/a&gt; package.
&lt;br /&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;about-solvers&#34;&gt;About Solvers&lt;/h2&gt;

&lt;p&gt;The real work of finding a solution is done by solvers, and writing
good solvers is hard work. Furthermore, some solvers work particularly
well for certain types of problems (linear programs, quadratic
programs, etc.). Not surprisingly, there are commercial vendors who
have solvers that are designed for performance and scale. Two
well-known solvers are &lt;a href=&#34;https://www.mosek.com&#34;&gt;MOSEK&lt;/a&gt; and
&lt;a href=&#34;https://www.gurobi.com&#34;&gt;GUROBI&lt;/a&gt;. R packages for these solvers are
also provided, but they require the problem data to be constructed in
a specific form. This necessitates a bit of work in the current version of
&lt;code&gt;CVXR&lt;/code&gt; and is certainly something we plan to include in future versions.
However, it is also true that these commercial solvers expose a much
richer API to Python programmers than to R programmers. How, then, do we
interface such solvers with R as quickly as possible, at least
in the short term?&lt;/p&gt;

&lt;h2 id=&#34;reticulate-to-the-rescue&#34;&gt;Reticulate to the Rescue&lt;/h2&gt;

&lt;p&gt;The current version of &lt;code&gt;CVXR&lt;/code&gt; exploits the
&lt;a href=&#34;https://cran.r-project.org/package=reticulate&#34;&gt;&lt;code&gt;reticulate&lt;/code&gt;&lt;/a&gt; package
for commercial solvers such as MOSEK and GUROBI. We took the Python solver interfaces in &lt;a href=&#34;http://www.cvxpy.org/versions/0.4.11/index.html&#34;&gt;&lt;code&gt;CVXPY&lt;/code&gt; version
0.4.11&lt;/a&gt;, edited them
suitably to make them self-contained, and hooked them up to &lt;code&gt;reticulate&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This means that one needs two prerequisites to use these commercial solvers in the current version of &lt;code&gt;CVXR&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A Python installation&lt;/li&gt;
&lt;li&gt;The &lt;a href=&#34;https://cran.r-project.org/package=reticulate&#34;&gt;&lt;code&gt;reticulate&lt;/code&gt;&lt;/a&gt; R
package.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;installing-mosek-gurobi&#34;&gt;Installing MOSEK/GUROBI&lt;/h2&gt;

&lt;p&gt;Both &lt;a href=&#34;https://www.mosek.com&#34;&gt;MOSEK&lt;/a&gt; and
&lt;a href=&#34;https://www.gurobi.com&#34;&gt;GUROBI&lt;/a&gt; provide academic versions
(registration required) free of charge. For example,
&lt;a href=&#34;https://www.anaconda.com&#34;&gt;Anaconda&lt;/a&gt; users can install MOSEK with the command:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash,&#34;&gt;conda install -c mosek mosek
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Others can use the &lt;code&gt;pip&lt;/code&gt; command:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash,&#34;&gt;pip install -f https://download.mosek.com/stable/wheel/index.html Mosek
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;GUROBI is handled in a similar fashion. The solvers must be activated using a
license provided by the vendor.&lt;/p&gt;

&lt;p&gt;Once activated, one can check that &lt;code&gt;CVXR&lt;/code&gt; recognizes the solver;
&lt;code&gt;installed_solvers()&lt;/code&gt; should list them.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;gt; installed_solvers()
[1] &amp;quot;ECOS&amp;quot;    &amp;quot;ECOS_BB&amp;quot; &amp;quot;SCS&amp;quot;     &amp;quot;MOSEK&amp;quot;   &amp;quot;LPSOLVE&amp;quot; &amp;quot;GLPK&amp;quot;    &amp;quot;GUROBI&amp;quot; 
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;further-information&#34;&gt;Further information&lt;/h2&gt;

&lt;p&gt;More information on these solvers, along with a number of tutorial examples are
available on the &lt;a href=&#34;https://cvxr.rbind.io&#34;&gt;CVXR&lt;/a&gt; site. If you are
attending &lt;a href=&#34;https://user2018.r-project.org&#34;&gt;useR! 2018&lt;/a&gt;, you can catch
Anqi&amp;rsquo;s &lt;code&gt;CVXR&lt;/code&gt; talk on Friday, July 13.&lt;/p&gt;

        &lt;script&gt;window.location.href=&#39;https://rviews.rstudio.com/2018/07/09/solver-interfaces-in-cvxr/&#39;;&lt;/script&gt;
      </description>
    </item>
    
    <item>
      <title>CVXR: An R Package for Disciplined Convex Optimization</title>
      <link>https://rviews.rstudio.com/2017/11/27/introduction-to-cvxr/</link>
      <pubDate>Mon, 27 Nov 2017 00:00:00 +0000</pubDate>
      
      <guid>https://rviews.rstudio.com/2017/11/27/introduction-to-cvxr/</guid>
      <description>
        


&lt;p&gt;At long last, we are pleased to announce the release of &lt;a href=&#34;http://CRAN.R-project.org/package=CVXR&#34;&gt;CVXR&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;First introduced at useR! 2016, &lt;code&gt;CVXR&lt;/code&gt; is an R package that provides an object-oriented language for convex optimization, similar to CVX, CVXPY, YALMIP, and Convex.jl. It allows the user to formulate convex optimization problems in a natural mathematical syntax, then automatically verifies the problem’s convexity with &lt;a href=&#34;http://dcp.stanford.edu&#34;&gt;disciplined convex programming (DCP)&lt;/a&gt; and converts it into the appropriate form for a specific solver. This makes &lt;code&gt;CVXR&lt;/code&gt; ideal for rapidly prototyping new statistical models. More information is available at the &lt;a href=&#34;http://cvxr.rbind.io&#34;&gt;official site&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This is the first of a series of blog posts about &lt;code&gt;CVXR&lt;/code&gt;. In this post, we will introduce the semantics of our package and dive into a simple example, which gives users an idea of &lt;code&gt;CVXR&lt;/code&gt;’s power.&lt;/p&gt;
&lt;div id=&#34;convex-optimization&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Convex Optimization&lt;/h2&gt;
&lt;p&gt;A convex optimization problem has the form &lt;span class=&#34;math display&#34;&gt;\[
\begin{array}{ll} \underset{v}{\mbox{minimize}} &amp;amp; f_0(v)\\
    \mbox{subject to} &amp;amp; f_i(v) \leq 0, \quad i=1,\ldots,M\\
    &amp;amp; g_i(v) = 0, \quad i=1,\ldots,P
    \end{array}
\]&lt;/span&gt; where &lt;span class=&#34;math inline&#34;&gt;\(v\)&lt;/span&gt; is the variable, &lt;span class=&#34;math inline&#34;&gt;\(f_0\)&lt;/span&gt; and &lt;span class=&#34;math inline&#34;&gt;\(f_1,...,f_m\)&lt;/span&gt; are convex, and &lt;span class=&#34;math inline&#34;&gt;\(g_1,...,g_p\)&lt;/span&gt; are affine. In &lt;code&gt;CVXR&lt;/code&gt;, variables, expressions, objectives, and constraints are all represented by S4 objects. Users define a problem by combining constants and variables with a library of basic functions (atoms) provided by the package. When &lt;code&gt;solve()&lt;/code&gt; is called, &lt;code&gt;CVXR&lt;/code&gt; converts the S4 object into a standard form, sends it to the user-specified solver, and retrieves the results. Let’s see an example of this in action.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;ordinary-least-squares-ols&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Ordinary Least Squares (OLS)&lt;/h2&gt;
&lt;p&gt;We begin by generating data for an ordinary least squares problem.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;set.seed(1)
s &amp;lt;- 1
n &amp;lt;- 10
m &amp;lt;- 300
mu &amp;lt;- rep(0, 9)
Sigma &amp;lt;- cbind(c(1.6484, -0.2096, -0.0771, -0.4088, 0.0678, -0.6337, 0.9720, -1.2158, -1.3219),
               c(-0.2096, 1.9274, 0.7059, 1.3051, 0.4479, 0.7384, -0.6342, 1.4291, -0.4723),
               c(-0.0771, 0.7059, 2.5503, 0.9047, 0.9280, 0.0566, -2.5292, 0.4776, -0.4552),
               c(-0.4088, 1.3051, 0.9047, 2.7638, 0.7607, 1.2465, -1.8116, 2.0076, -0.3377),
               c(0.0678, 0.4479, 0.9280, 0.7607, 3.8453, -0.2098, -2.0078, -0.1715, -0.3952),
               c(-0.6337, 0.7384, 0.0566, 1.2465, -0.2098, 2.0432, -1.0666,  1.7536, -0.1845),
               c(0.9720, -0.6342, -2.5292, -1.8116, -2.0078, -1.0666, 4.0882,  -1.3587, 0.7287),
               c(-1.2158, 1.4291, 0.4776, 2.0076, -0.1715, 1.7536, -1.3587, 2.8789, 0.4094),
               c(-1.3219, -0.4723, -0.4552, -0.3377, -0.3952, -0.1845, 0.7287, 0.4094, 4.8406))
X &amp;lt;- mvrnorm(m, mu, Sigma)
X &amp;lt;- cbind(rep(1, m), X)
trueBeta &amp;lt;- c(0, 0.8, 0, 1, 0.2, 0, 0.4, 1, 0, 0.7)
y &amp;lt;- X %*% trueBeta + rnorm(m, 0, s)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here, &lt;code&gt;n&lt;/code&gt; is the number of predictors, &lt;code&gt;y&lt;/code&gt; is the response, and &lt;code&gt;X&lt;/code&gt; is the matrix of predictors. In &lt;code&gt;CVXR&lt;/code&gt;, we first instantiate the optimization variable.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;beta &amp;lt;- Variable(n)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;beta&lt;/code&gt; is a &lt;code&gt;Variable&lt;/code&gt; S4 object, which does not contain a value yet.&lt;/p&gt;
&lt;p&gt;In the next line, we define the objective function.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;objective &amp;lt;- Minimize(sum((y - X %*% beta)^2))&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The expression &lt;code&gt;sum((y - X %*% beta)^2)&lt;/code&gt; is another S4 object, created by combining &lt;code&gt;y&lt;/code&gt;, &lt;code&gt;X&lt;/code&gt;, and &lt;code&gt;beta&lt;/code&gt; using the basic addition, subtraction, multiplication, and power atoms. Thus, the call to &lt;code&gt;Minimize()&lt;/code&gt; does &lt;em&gt;not&lt;/em&gt; return its minimum value (after all, &lt;code&gt;beta&lt;/code&gt; doesn’t have a value yet, so we cannot evaluate the expression), but simply defines the goal of our optimization problem.&lt;/p&gt;
&lt;p&gt;Finally, we construct the &lt;code&gt;Problem&lt;/code&gt; and call &lt;code&gt;solve()&lt;/code&gt;, which invokes the default ECOS solver.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;prob &amp;lt;- Problem(objective)
CVXR_result &amp;lt;- solve(prob)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This returns a list containing, among other things, the solver status, objective value, and function &lt;code&gt;getValue()&lt;/code&gt; that takes as input a &lt;code&gt;Variable&lt;/code&gt; and retrieves its optimal value from the solution.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;CVXR_result$status           # solution status by solver&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;optimal&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;CVXR_result$value            # optimal objective value&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] 340.3187&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;cvxrBeta &amp;lt;- CVXR_result$getValue(beta)   # optimal value of beta&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Below, we plot the &lt;code&gt;CVXR&lt;/code&gt; coefficients beside the coefficients found by &lt;code&gt;lm()&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;p &amp;lt;- length(trueBeta)
lm_result &amp;lt;- lm(y ~ 0 + X)
lmBeta &amp;lt;- coef(lm_result)
df &amp;lt;- data.frame(coeff = rep(paste0(&amp;quot;beta[&amp;quot;, seq_along(lmBeta) - 1L, &amp;quot;]&amp;quot;), 2),
                beta = c(lmBeta, cvxrBeta),
                type = c(rep(&amp;quot;OLS&amp;quot;, p), rep(&amp;quot;CVXR&amp;quot;, p)))
ggplot(data = df, mapping = aes(x = coeff, y = beta)) +
    geom_bar(mapping = aes(fill = type), stat = &amp;quot;identity&amp;quot;, position = &amp;quot;dodge&amp;quot;) +
    scale_x_discrete(labels = parse(text = levels(df$coeff)))&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;/post/2017-11-21-introduction-to-cvxr_files/figure-html/unnamed-chunk-6-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;p&gt;As expected, they are identical. Obviously, if all you want to fit is OLS, you should use &lt;code&gt;lm()&lt;/code&gt;. The chief advantage of &lt;code&gt;CVXR&lt;/code&gt; is its ability to quickly modify and adapt a problem, as we illustrate in the next section.&lt;/p&gt;
&lt;div id=&#34;non-negative-least-squares-nnls&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Non-Negative Least Squares (NNLS)&lt;/h3&gt;
&lt;p&gt;In many situations, we can greatly improve our model by constraining the solution to reflect our prior knowledge. For example, we may know that &lt;code&gt;beta&lt;/code&gt; must be non-negative. We can easily incorporate this knowledge into our problem by passing an additional argument to the &lt;code&gt;Problem()&lt;/code&gt; constructor, which specifies a list of constraints.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;prob2 &amp;lt;- Problem(objective, list(beta &amp;gt;= 0))&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Again, counter to what you might expect, the expression &lt;code&gt;beta &amp;gt;= 0&lt;/code&gt; does not return &lt;code&gt;TRUE&lt;/code&gt; or &lt;code&gt;FALSE&lt;/code&gt; the way &lt;code&gt;1.3 &amp;gt;= 0&lt;/code&gt; would. Instead, the &lt;code&gt;==&lt;/code&gt; and &lt;code&gt;&amp;gt;=&lt;/code&gt; operators have been overloaded to return &lt;code&gt;Constraint&lt;/code&gt; S4 objects, which will be used by the solver to enforce the problem’s constraints. We then re-solve the new problem with the non-negativity constraint.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;CVXR_result2 &amp;lt;- solve(prob2)
cvxrBetaNNLS &amp;lt;- CVXR_result2$getValue(beta)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see in the figure below, adding that one constraint produced a massive improvement in the accuracy of the estimates. Not only are the NNLS estimates much closer to the true coefficients than the OLS estimates, but they have even managed to recover the correct sparsity structure in this case.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;df &amp;lt;- data.frame(coeff = rep(paste0(&amp;quot;beta[&amp;quot;, seq_along(trueBeta) - 1L, &amp;quot;]&amp;quot;), 3),
                beta = c(trueBeta, lmBeta, cvxrBetaNNLS),
                type = c(rep(&amp;quot;Actual&amp;quot;, p), rep(&amp;quot;OLS&amp;quot;, p), rep(&amp;quot;NNLS&amp;quot;, p)))
ggplot(data = df, mapping = aes(x = coeff, y = beta)) +
    geom_bar(mapping = aes(fill = type), stat = &amp;quot;identity&amp;quot;, position = &amp;quot;dodge&amp;quot;) +
    scale_x_discrete(labels = parse(text = levels(df$coeff)))&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;/post/2017-11-21-introduction-to-cvxr_files/figure-html/unnamed-chunk-9-1.png&#34; width=&#34;700&#34; /&gt;&lt;/p&gt;
&lt;p&gt;Like with OLS, there are already R packages available that implement NNLS. But that is actually an excellent demonstration of the power of &lt;code&gt;CVXR&lt;/code&gt;: A single line of code here - namely, &lt;code&gt;prob2 &amp;lt;- Problem(objective, list(beta &amp;gt;= 0))&lt;/code&gt; - is doing the work of an entire package.&lt;/p&gt;
&lt;p&gt;We hope this gives you an idea of the power of &lt;code&gt;CVXR&lt;/code&gt;. In our next post, we will explore a non-parametric estimation problem that introduces more atoms and constraints.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

        &lt;script&gt;window.location.href=&#39;https://rviews.rstudio.com/2017/11/27/introduction-to-cvxr/&#39;;&lt;/script&gt;
      </description>
    </item>
    
  </channel>
</rss>
