<p><div><div><div><div data-width="100" data-show-faces="false" data-send="true" data-layout="button_count" data-height="21" data-href="https://www.r-bloggers.com/mean-and-quantile-regression-using-mosek-2/"></div></div><div></div></div><div></div></div>
<div>
(This article was first published on <strong><a href="https://ignaciomsarmiento.github.io/2017/01/20/Quantile-and-OLS-Regression-with-Rmosek.html"> Ignacio Sarmiento Barbieri</a></strong>, and kindly contributed to <a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers)</a> </div>
<p>Many of the problems we encounter in Econometrics can be formulated as a linear or a quadratic problem. In this post, I want to approach two traditional problems: Quantile Regression and Ordinary Least Squares as convex problems and how to implement them in <em>R</em> using the package <em>RMosek</em>.</p>
<p>There are many convex optimizer solvers available for <em>R</em>, a survey can be found at the <a target="_blank" rel="nofollow" href="https://cran.r-project.org/web/views/Optimization.html"><em>CRAN Task View: Optimization and Mathematical Programming</em></a>. But here, I want to center my attention on <em>Rmosek</em> (Friberg 2014). <em>Rmosek</em> is an interface that makes available <em>Mosek</em> from R and it’s available from <a target="_blank" rel="nofollow" href="http://cran.r-project/">CRAN</a>. <em>Mosek</em> is an “optimization software designed to solve large-scale mathematical optimization problems” (Mosek, 2011). Probably one of <em>Mosek’s</em> greatest features is that nonlinear separable convex optimization problems can be easily implemented and solved.</p>
<p>I begin this post by writing the Quantile and Ordinary Least Squares problems in their linear and quadratic forms respectively. Outlined the analytic form, I write functions that implement them in <em>Rmosek</em>. Finally, I test my <em>Rmosek</em> function to benchmark <code>R</code> functions in a simulation exercise, and in a replication exercise. Overall, once the analytic forms of the problems are outline its translation to <em>Rmosek</em> is quite easy and they perform fairly well for moderately large problems.</p>
<h3>Quantile Regression</h3>
<p>The Quantile Regression problem solves the following problem</p>
<p></p>
<p>which can be written as a linear program. Let  be a  matrix of regressors with a constant, and  an  vector of the dependent variable. Following Koenker (2005) we can write the quantile problem as a linear problem,</p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p>Recall that the primal problem in a linear program can be written as</p>
<p></p>
<p></p>
<p></p>
<p></p>
<p>To translate this problem into <em>Rmosek</em> it is useful to make the following correspondences:</p>
<p></p>
<p>where  is an n-vector of ones.</p>
<p></p>
<p></p>
<p>furthermore, note that  and that in this case .</p>
<p>The next step is then to write our own quantile regression function that wraps <em>Rmosek</em>. I call the function <code>qr.mosek</code> and give it as inputs the design X matrix (that should contain a column of ones if the model has a constant) and the dependent variable. Also, takes a variable <code>verb</code> that controls for the “verbosity” of the output’s log. The function begins by getting the relevant dimensions from the data. Then it defines the problem in Mosek. The problem definition starts with an empty list, which I called <em>lo1</em>. The next step is defining the objective goal, which in this case is minimization (<code>&quot;min&quot;</code>). Then we pass the variables following the above correspondences. The last line solves the problem. When defining the problem <a target="_blank" rel="nofollow" href="https://r-forge.r-project.org/scm/viewvc.php/*checkout*/pkg/inst/doc/userguide.pdf?root=rmosek">Rmosek Users Guide</a> becomes a very handy tool, and I follow it closely.</p>
<div>
<pre><code><span>qr.mosek</span><span>&lt;-</span><span>function</span><span>(</span><span>X</span><span>,</span><span>y</span><span>,</span><span>tau</span><span>,</span><span> </span><span>verb</span><span>=</span><span>1</span><span>){</span><span>
</span><span>n</span><span>&lt;-</span><span>length</span><span>(</span><span>y</span><span>)</span><span> </span><span>#number of observations
</span><span> </span><span>p</span><span>&lt;-</span><span>dim</span><span>(</span><span>X</span><span>)[</span><span>2</span><span>]</span><span> </span><span># number of parameters of interest
</span><span>
</span><span>#problem definition in Mosek
</span><span> </span><span>lo1</span><span>&lt;-</span><span>list</span><span>()</span><span> </span><span>#empty list that contains the LP problem
</span><span> </span><span>lo1</span><span>$</span><span>sense</span><span>&lt;-</span><span>&quot;min&quot;</span><span> </span><span>#problem sense
</span><span> </span><span>lo1</span><span>$</span><span>c</span><span>&lt;-</span><span>c</span><span>(</span><span>rep</span><span>(</span><span>0</span><span>,</span><span>p</span><span>),</span><span>rep</span><span>(</span><span>tau</span><span>,</span><span>n</span><span>),</span><span>rep</span><span>((</span><span>1</span><span>-</span><span>tau</span><span>),</span><span>n</span><span>))</span><span> </span><span>#objective coefficients
</span><span> </span><span>lo1</span><span>$</span><span>A</span><span>&lt;-</span><span>Matrix</span><span>(</span><span>cbind</span><span>(</span><span>X</span><span>,</span><span>diag</span><span>(</span><span>n</span><span>),</span><span>-</span><span>diag</span><span>(</span><span>n</span><span>)),</span><span>sparse</span><span>=</span><span>TRUE</span><span>)</span><span> </span><span>#constraint matrix
</span><span> </span><span>lo1</span><span>$</span><span>bc</span><span>&lt;-</span><span>rbind</span><span>(</span><span>blc</span><span>=</span><span>c</span><span>(</span><span>y</span><span>),</span><span>buc</span><span>=</span><span>c</span><span>(</span><span>y</span><span>))</span><span> </span><span>#lower and upper constraint bounds
</span><span> </span><span>blx</span><span>&lt;-</span><span>c</span><span>(</span><span>rep</span><span>(</span><span>-</span><span>Inf</span><span>,</span><span>p</span><span>),</span><span>rep</span><span>(</span><span>0</span><span>,</span><span>n</span><span>),</span><span>rep</span><span>(</span><span>0</span><span>,</span><span>n</span><span>))</span><span> </span><span>#lower parameters bounds
</span><span> </span><span>bux</span><span>&lt;-</span><span>c</span><span>(</span><span>rep</span><span>(</span><span>Inf</span><span>,</span><span>p</span><span>),</span><span>rep</span><span>(</span><span>Inf</span><span>,</span><span>n</span><span>),</span><span>rep</span><span>(</span><span>Inf</span><span>,</span><span>n</span><span>))</span><span> </span><span>#upper parameters bounds
</span><span> </span><span>lo1</span><span>$</span><span>bx</span><span>&lt;-</span><span>rbind</span><span>(</span><span>blx</span><span>,</span><span>bux</span><span>)</span><span> </span><span>#bind the lower and upper paramenter bounds
</span><span>
</span><span>r</span><span>&lt;-</span><span>mosek</span><span>(</span><span>lo1</span><span>,</span><span> </span><span>opts</span><span> </span><span>=</span><span> </span><span>list</span><span>(</span><span>verbose</span><span> </span><span>=</span><span> </span><span>verb</span><span>))</span><span> </span><span>#call mosek solver
</span><span> </span><span>return</span><span>(</span><span>r</span><span>)</span><span>
</span><span>}</span><span>
</span></code></pre>
</div>
<p>Mosek uses as default its interior point algorithm and returns an interior point solution and a vertex solution. The primal interior point solution is called <em>itr</em> and can be obtained via <code>$sol$itr$xx</code>. One must be careful when retrieving the solution because we introduced 2<em>n</em> slack variables in the problem. The option <code>verbose</code> on Mosek controls messages priorities, option 1 prints when errors are encountered. Setting it to 0 will silence Mosek completely. The option <code>optimizer</code> can also be specified and allows the user to let Mosek choose the optimizer, or choose an interior point algorithm, or a simplex method on the primal, among others.</p>
<p>The primal form gets “a bit unwieldy” (Koenker and Mizera, 2014) because of these 2<em>n</em> slack variables. However, the problem can be written in the corresponding dual form, which is more convenient for interior point implementations.</p>
<p></p>
<p></p>
<p></p>
<p></p>
<p>A function using Mosek will look like;</p>
<div>
<pre><code><span>qr.mosek.dual</span><span>&lt;-</span><span>function</span><span>(</span><span>X</span><span>,</span><span>y</span><span>,</span><span>tau</span><span>,</span><span> </span><span>verb</span><span>=</span><span>1</span><span>){</span><span>
</span><span>n</span><span>&lt;-</span><span>length</span><span>(</span><span>y</span><span>)</span><span> </span><span>#number of observations
</span><span> </span><span>p</span><span>&lt;-</span><span>dim</span><span>(</span><span>X</span><span>)[</span><span>2</span><span>]</span><span> </span><span># number of parameters of interest
</span><span>
</span><span>#problem definition in Mosek
</span><span> </span><span>lo1</span><span>&lt;-</span><span>list</span><span>()</span><span> </span><span>#empty list that contains the LP problem
</span><span> </span><span>lo1</span><span>$</span><span>sense</span><span>&lt;-</span><span>&quot;max&quot;</span><span> </span><span>#problem sense
</span><span> </span><span>lo1</span><span>$</span><span>c</span><span>&lt;-</span><span>as.vector</span><span>(</span><span>y</span><span>)</span><span> </span><span>#objective coefficients
</span><span> </span><span>lo1</span><span>$</span><span>A</span><span>&lt;-</span><span>Matrix</span><span>(</span><span>t</span><span>(</span><span>X</span><span>),</span><span>sparse</span><span>=</span><span>TRUE</span><span>)</span><span> </span><span>#constraint matrix
</span><span> </span><span>blc</span><span>&lt;-</span><span>rep</span><span>(</span><span>0</span><span>,</span><span>p</span><span>)</span><span> </span><span>#lower constraint bounds
</span><span> </span><span>buc</span><span>&lt;-</span><span>rep</span><span>(</span><span>0</span><span>,</span><span>p</span><span>)</span><span> </span><span>#upper constraint bounds
</span><span> </span><span>lo1</span><span>$</span><span>bc</span><span>&lt;-</span><span>rbind</span><span>(</span><span>blc</span><span>,</span><span>buc</span><span>)</span><span> </span><span>#bind the lower and upper constraint bounds
</span><span> </span><span>blx</span><span>&lt;-</span><span>c</span><span>(</span><span>rep</span><span>(</span><span>tau</span><span>-1</span><span>,</span><span>n</span><span>))</span><span> </span><span>#lower parameters bounds
</span><span> </span><span>bux</span><span>&lt;-</span><span>c</span><span>(</span><span>rep</span><span>(</span><span>tau</span><span>,</span><span>n</span><span>))</span><span> </span><span>#upper parameters bounds
</span><span> </span><span>lo1</span><span>$</span><span>bx</span><span>&lt;-</span><span>rbind</span><span>(</span><span>blx</span><span>,</span><span>bux</span><span>)</span><span> </span><span>#bind the lower and upper parameter bounds
</span><span>
</span><span>r</span><span>&lt;-</span><span>mosek</span><span>(</span><span>lo1</span><span>,</span><span> </span><span>opts</span><span> </span><span>=</span><span> </span><span>list</span><span>(</span><span>verbose</span><span> </span><span>=</span><span> </span><span>verb</span><span>))</span><span> </span><span>#call mosek solver
</span><span> </span><span>return</span><span>(</span><span>r</span><span>)</span><span>
</span><span>}</span><span>
</span></code></pre>
</div>
<p>Equivalently, the may be reparametrized as</p>
<p></p>
<p></p>
<p></p>
<p></p>
<p>and its implementation in <em>Rmosek</em></p>
<div>
<pre><code><span>qr.mosek.dual.rep</span><span>&lt;-</span><span>function</span><span>(</span><span>X</span><span>,</span><span>y</span><span>,</span><span>tau</span><span>,</span><span> </span><span>verb</span><span>=</span><span>1</span><span>){</span><span>
</span><span>n</span><span>&lt;-</span><span>length</span><span>(</span><span>y</span><span>)</span><span> </span><span>#number of observations
</span><span> </span><span>p</span><span>&lt;-</span><span>dim</span><span>(</span><span>X</span><span>)[</span><span>2</span><span>]</span><span> </span><span># number of parameters of interest
</span><span>
</span><span>#problem definition in Mosek
</span><span> </span><span>lo1</span><span>&lt;-</span><span>list</span><span>()</span><span> </span><span>#empty list that contains the LP problem
</span><span> </span><span>lo1</span><span>$</span><span>sense</span><span>&lt;-</span><span>&quot;max&quot;</span><span> </span><span>#problem sense
</span><span> </span><span>lo1</span><span>$</span><span>c</span><span>&lt;-</span><span>as.vector</span><span>(</span><span>y</span><span>)</span><span> </span><span>#objective coefficients
</span><span> </span><span>lo1</span><span>$</span><span>A</span><span>&lt;-</span><span>Matrix</span><span>(</span><span>t</span><span>(</span><span>X</span><span>),</span><span>sparse</span><span>=</span><span>TRUE</span><span>)</span><span> </span><span>#constraint matrix
</span><span> </span><span>e</span><span>&lt;-</span><span>matrix</span><span>(</span><span>1</span><span>,</span><span>ncol</span><span>=</span><span>1</span><span>,</span><span>nrow</span><span>=</span><span>n</span><span>)</span><span> </span><span>#vector of ones
</span><span> </span><span>blc</span><span>&lt;-</span><span>(</span><span>1</span><span>-</span><span>tau</span><span>)</span><span>*</span><span>c</span><span>(</span><span>crossprod</span><span>(</span><span>X</span><span>,</span><span>e</span><span>))</span><span> </span><span>#lower constraint bounds
</span><span> </span><span>buc</span><span>&lt;-</span><span>(</span><span>1</span><span>-</span><span>tau</span><span>)</span><span>*</span><span>c</span><span>(</span><span>crossprod</span><span>(</span><span>X</span><span>,</span><span>e</span><span>))</span><span> </span><span>#upper constraint bounds
</span><span> </span><span>lo1</span><span>$</span><span>bc</span><span>&lt;-</span><span>rbind</span><span>(</span><span>blc</span><span>,</span><span>buc</span><span>)</span><span> </span><span>#bind the lower and upper constraint bounds
</span><span> </span><span>blx</span><span>&lt;-</span><span>c</span><span>(</span><span>rep</span><span>(</span><span>0</span><span>,</span><span>n</span><span>))</span><span> </span><span>#lower parameters bounds
</span><span> </span><span>bux</span><span>&lt;-</span><span>c</span><span>(</span><span>rep</span><span>(</span><span>1</span><span>,</span><span>n</span><span>))</span><span> </span><span>#upper parameters bounds
</span><span> </span><span>lo1</span><span>$</span><span>bx</span><span>&lt;-</span><span>rbind</span><span>(</span><span>blx</span><span>,</span><span>bux</span><span>)</span><span> </span><span>#bind the lower and upper parameter bounds
</span><span>
</span><span>r</span><span>&lt;-</span><span>mosek</span><span>(</span><span>lo1</span><span>,</span><span> </span><span>opts</span><span> </span><span>=</span><span> </span><span>list</span><span>(</span><span>verbose</span><span> </span><span>=</span><span> </span><span>verb</span><span>))</span><span> </span><span>#call mosek solver
</span><span> </span><span>return</span><span>(</span><span>r</span><span>)</span><span>
</span><span>}</span><span>
</span></code></pre>
</div>
<p>Again, the solution to the interior point method is accessed via <code>$sol$itr</code>. In these cases, we must be careful because we want to retrieve the solution to the dual variables.</p>
<h2>OLS as a Quadratic Program</h2>
<p>Now I turn to our more familiar Ordinary Least Squares. It solves</p>
<p></p>
<p>with a little use of algebra, we can write this problem as a Quadratic Program</p>
<p></p>
<p>recall that a general form of a Quadratic program is<br>
</p>
<p></p>
<p></p>
<p>so, making the appropriate correspondences we have the Ordinary Least Squares problem. Note that the OLS case, is unconstrained, which will become handy when specifying the problem in the solver.</p>
<p>To implement the problem in <em>Rmosek</em> I proceed as before. First, I create a function that wraps the definition of the optimization problem and <em>Mosek’s</em> optimizer. The function is called <code>solve.ols</code> and has the same inputs and options as before. The first half of the function is devoted to setting the correspondences between OLS and the Quadratic Program, the second half we simple follow <a target="_blank" rel="nofollow" href="https://r-forge.r-project.org/scm/viewvc.php/*checkout*/pkg/inst/doc/userguide.pdf?root=rmosek">Rmosek Users Guide</a> to define the minimization problem.</p>
<div>
<pre><code><span>solve.ols</span><span>&lt;-</span><span>function</span><span>(</span><span>X</span><span>,</span><span>y</span><span>,</span><span> </span><span>verb</span><span>=</span><span>1</span><span>){</span><span>
</span><span>p</span><span>&lt;-</span><span>dim</span><span>(</span><span>X</span><span>)[</span><span>2</span><span>]</span><span> </span><span># number of parameters of interest
</span><span>
</span><span>#correspondence between OLS and the Quadratic Program
</span><span> </span><span>xx</span><span>&lt;-</span><span>crossprod</span><span>(</span><span>X</span><span>)</span><span> </span><span># X'X=Q variable in the Quadratic program
</span><span> </span><span>c</span><span>&lt;--</span><span>crossprod</span><span>(</span><span>X</span><span>,</span><span>y</span><span>)</span><span> </span><span># X'y=c variable in the Quadratic program
</span><span> </span><span>xx2</span><span>&lt;-</span><span>xx</span><span>
</span><span>xx2</span><span>[</span><span>upper.tri</span><span>(</span><span>xx</span><span>)]</span><span>&lt;</span><span>-0</span><span> </span><span>#mosek needs Q to be triangular
</span><span> </span><span>idx</span><span> </span><span>&lt;-</span><span> </span><span>which</span><span>(</span><span>xx2</span><span> </span><span>!=</span><span> </span><span>0</span><span>,</span><span> </span><span>arr.ind</span><span>=</span><span>TRUE</span><span>)</span><span> </span><span>#index of the nonzero elements of Q
</span><span>
</span><span>#problem definition in Mosek
</span><span> </span><span>qo1</span><span>&lt;-</span><span>list</span><span>()</span><span> </span><span>#empty list that contains the QP problem
</span><span> </span><span>qo1</span><span>$</span><span>sense</span><span>&lt;-</span><span>&quot;min&quot;</span><span> </span><span>#problem sense
</span><span> </span><span>qo1</span><span>$</span><span>c</span><span>&lt;-</span><span>as.vector</span><span>(</span><span>c</span><span>)</span><span> </span><span>#objective coefficients
</span><span> </span><span>qo1</span><span>$</span><span>qobj</span><span>&lt;-</span><span>list</span><span>(</span><span>i</span><span> </span><span>=</span><span> </span><span>idx</span><span>[,</span><span>1</span><span>],</span><span>
</span><span>j</span><span> </span><span>=</span><span> </span><span>idx</span><span>[,</span><span>2</span><span>],</span><span>
</span><span>v</span><span> </span><span>=</span><span> </span><span>xx2</span><span>[</span><span>idx</span><span>]</span><span> </span><span>)</span><span> </span><span>#the Q matrix is imputed by the row indexes i, the col indexes j and the values v that define the Q matrix
</span><span> </span><span>qo1</span><span>$</span><span>A</span><span>&lt;-</span><span>Matrix</span><span>(</span><span>rep</span><span>(</span><span>0</span><span>,</span><span>p</span><span>),</span><span> </span><span>nrow</span><span>=</span><span>1</span><span>,</span><span>byrow</span><span>=</span><span>TRUE</span><span>,</span><span>sparse</span><span>=</span><span>TRUE</span><span>)</span><span> </span><span>#constrain matrix A is a null matrix in this case
</span><span> </span><span>qo1</span><span>$</span><span>bc</span><span>&lt;-</span><span>rbind</span><span>(</span><span>blc</span><span>=-</span><span>Inf</span><span>,</span><span> </span><span>buc</span><span>=</span><span> </span><span>Inf</span><span>)</span><span> </span><span>#constraint bounds
</span><span> </span><span>qo1</span><span>$</span><span>bx</span><span>&lt;-</span><span>rbind</span><span>(</span><span>blx</span><span>=</span><span>rep</span><span>(</span><span>-</span><span>Inf</span><span>,</span><span>p</span><span>),</span><span> </span><span>bux</span><span> </span><span>=</span><span> </span><span>rep</span><span>(</span><span>Inf</span><span>,</span><span>p</span><span>))</span><span> </span><span>#parameter bounds
</span><span>
</span><span>r</span><span>&lt;-</span><span>mosek</span><span>(</span><span>qo1</span><span>,</span><span> </span><span>opts</span><span> </span><span>=</span><span> </span><span>list</span><span>(</span><span>verbose</span><span> </span><span>=</span><span> </span><span>verb</span><span>))</span><span> </span><span>#call mosek solver
</span><span> </span><span>return</span><span>(</span><span>r</span><span>)</span><span>
</span><span>}</span><span>
</span></code></pre>
</div>
<h2>Applications</h2>
<h3>Simulation</h3>
<p>We are now ready to test our function. I set a mock problem where the independent variable does not have an effect on the conditional mean but the effect is on the variance.</p>
<div>
<pre><code><span>set.seed</span><span>(</span><span>1212</span><span>)</span><span>
</span><span>x</span><span>&lt;-</span><span>rep</span><span>(</span><span>1</span><span>:</span><span>20</span><span>,</span><span>each</span><span>=</span><span>500</span><span>)</span><span>
</span><span>n</span><span>&lt;-</span><span>length</span><span>(</span><span>x</span><span>)</span><span>
</span><span>cons</span><span>&lt;-</span><span>rep</span><span>(</span><span>1</span><span>,</span><span>n</span><span>)</span><span>
</span><span>X</span><span>&lt;-</span><span>cbind</span><span>(</span><span>cons</span><span>,</span><span>x</span><span>)</span><span>
</span><span>y</span><span>&lt;-</span><span>rnorm</span><span>(</span><span>n</span><span>,</span><span>mean</span><span>=</span><span>0</span><span>,</span><span>sd</span><span>=</span><span>x</span><span>^</span><span>.8</span><span>)</span><span>
</span></code></pre>
</div>
<p>Plotting the simulation clearly shows how that the effect of the independent variable on the mean is zero but the variance increases with it.<br>
<code>r<br>
plot(x,y)<br>
</code></p>
<p><img align="middle" src="https://i0.wp.com/ignaciomsarmiento.github.io/assets/images/quantile_figure.png?w=400&ssl=1" data-recalc-dims="1"> </p>
<p>First, once we have installed <em>Rmosek</em>, we call it</p>
<div>
<pre><code><span>require</span><span>(</span><span>Rmosek</span><span>,</span><span> </span><span>quietly</span><span> </span><span>=</span><span> </span><span>T</span><span>)</span><span>
</span></code></pre>
</div>
<p>Suppose we want to assess the effect on the median (<em>τ</em> = .5)</p>
<div>
<pre><code><span>tau</span><span>&lt;</span><span>-0.50</span><span>
</span><span>z</span><span>&lt;-</span><span>qr.mosek</span><span>(</span><span>X</span><span>,</span><span>y</span><span>,</span><span>tau</span><span>=</span><span>tau</span><span>)</span><span>
</span><span>head</span><span>(</span><span>z</span><span>$</span><span>sol</span><span>$</span><span>itr</span><span>$</span><span>xx</span><span>,</span><span>dim</span><span>(</span><span>X</span><span>)[</span><span>2</span><span>])</span><span>
</span></code></pre>
</div>
<div>
<pre><code>[1] -0.039657474  0.008174528
</code></pre>
</div>
<p>The parameter results are located under <code>$sol$itr$xx</code>. Note that the parameters of interest are only the first <em>p</em> parameters. The solution includes <em>p</em> × 2<em>n</em> results, <em>p</em> parameters and 2<em>n</em> slack variables, but only the first <em>p</em> are of interest. As expected the effect on the median is null.</p>
<p>Suppose now that we want to assess the effect on the 90<em>t**h</em> quantile, where we should expect a positive effect of the independent variable.</p>
<div>
<pre><code><span>tau</span><span>&lt;</span><span>-0.90</span><span>
</span><span>z</span><span>&lt;-</span><span>qr.mosek</span><span>(</span><span>X</span><span>,</span><span>y</span><span>,</span><span>tau</span><span>=</span><span>tau</span><span>)</span><span>
</span><span>head</span><span>(</span><span>z</span><span>$</span><span>sol</span><span>$</span><span>itr</span><span>$</span><span>xx</span><span>,</span><span>dim</span><span>(</span><span>X</span><span>)[</span><span>2</span><span>])</span><span>
</span></code></pre>
</div>
<div>
<pre><code>[1] 1.0165950 0.6772688
</code></pre>
</div>
<p>To compare <em>Mosek</em> performance we choose <code>quantreg</code> package (Koenker, 2016), which is the most used package to solve this type of problems in <code>R</code>. The default solver in the <code>quantreg</code> package is the function <code>rq.fit.br</code>. This function calls algorithm of Koenker and d’Orey (Koenker, 2016).</p>
<div>
<pre><code><span>require</span><span>(</span><span>quantreg</span><span>)</span><span>
</span></code></pre>
</div>
<div>
<pre><code><span>rq.fit.br</span><span>(</span><span>X</span><span>,</span><span>y</span><span>,</span><span>tau</span><span>=</span><span>tau</span><span>)</span><span>$</span><span>coefficients</span><span>
</span></code></pre>
</div>
<div>
<pre><code>     cons         x
1.0165950 0.6772688
</code></pre>
</div>
<p>Results are numerically identical under Mosek and the <code>quantreg</code> package. More interesting however is testing how Mosek solver compares in computation time to the <code>quantreg</code> package default. I test then the primal, the dual, and the reparametrized dual, against the function <code>rq.fit.br</code></p>
<div>
<pre><code><span>microbenchmark</span><span>::</span><span>microbenchmark</span><span>(</span><span>
</span><span>qr.mosek</span><span>(</span><span>X</span><span>,</span><span>y</span><span>,</span><span>tau</span><span>=</span><span>tau</span><span>),</span><span>
</span><span>qr.mosek.dual</span><span>(</span><span>X</span><span>,</span><span>y</span><span>,</span><span>tau</span><span>=</span><span>tau</span><span>),</span><span>
</span><span>qr.mosek.dual.rep</span><span>(</span><span>X</span><span>,</span><span>y</span><span>,</span><span>tau</span><span>=</span><span>tau</span><span>),</span><span>
</span><span>rq.fit.br</span><span>(</span><span>X</span><span>,</span><span>y</span><span>,</span><span>tau</span><span>=</span><span>tau</span><span>)</span><span>
</span><span>)</span><span>
</span></code></pre>
</div>
<div>
<pre><code>Unit: milliseconds
                               expr         min          lq        mean
          qr.mosek(X, y, tau = tau) 2866.959432 3132.532709 3238.346004
     qr.mosek.dual(X, y, tau = tau)   93.354619   95.710071   98.888875
 qr.mosek.dual.rep(X, y, tau = tau)   93.863603   95.716660   98.375217
         rq.fit.br(X, y, tau = tau)    8.280732    8.459964    8.892775
      median          uq        max neval
 3172.331852 3355.718077 3809.76471   100
   96.661428   99.848480  128.10002   100
   96.848799   99.052075  120.14091   100
    8.582349    8.987302   12.99779   100
</code></pre>
</div>
<p>It’s clear now how unwieldy the primal problem. It takes considerably more time than the dual formulations or the <code>rq.fit.br</code> function. And the dual formulations in Mosek are considerable slower than the <code>rq.fit.br</code> function.</p>
<p>Next, I examine how the OLS solver works. First, I call the function I constructed before</p>
<div>
<pre><code><span>solve.ols</span><span>(</span><span>X</span><span>,</span><span>y</span><span>)</span><span>$</span><span>sol</span><span>$</span><span>itr</span><span>$</span><span>xx</span><span>
</span></code></pre>
</div>
<div>
<pre><code>[1]  0.020485604 -0.005660287
</code></pre>
</div>
<p>and I compare it to the traditional <code>lm</code> function in the <code>base</code> package</p>
<div>
<pre><code><span>summary</span><span>(</span><span>lm</span><span>(</span><span>y</span><span> </span><span>~</span><span> </span><span>X</span><span>-1</span><span>))</span><span>$</span><span>coef</span><span>[,</span><span>1</span><span>]</span><span>
</span></code></pre>
</div>
<div>
<pre><code>       Xcons           Xx
 0.020485604 -0.005660287
</code></pre>
</div>
<p>note the −1 in the <code>lm</code> line because the <em>X</em> already includes a constant in <em>X</em>. Once again numerically they are identical. Comparing times, I find that Mosek is quite considerably faster than the base <code>lm</code>. I should test however this with more complex problems.</p>
<div>
<pre><code><span>microbenchmark</span><span>::</span><span>microbenchmark</span><span>(</span><span>
</span><span>lm</span><span>(</span><span>y</span><span> </span><span>~</span><span> </span><span>X</span><span>-1</span><span>),</span><span>
</span><span>solve.ols</span><span>(</span><span>X</span><span>,</span><span>y</span><span>)</span><span>
</span><span>)</span><span>
</span></code></pre>
</div>
<div>
<pre><code>Unit: milliseconds
    expr          min       lq      mean      median        uq
lm(y ~ X - 1)   6.063136 9.518182 10.313522   9.809023  10.261577
solve.ols(X, y) 1.007566 1.164319  2.313304   1.426241   1.547576
  max      neval
60.70589    100
82.68025    100
</code></pre>
</div>
<h3>Replication: The Wage Distribution</h3>
<p>Next, I turn to an application taken from Mostly Harmless Econometrics (Angrist &amp; Pischke, 2008). The application replicates Angrist, et al (2006) <em>Quantile Regression under Misspecification, with an Application to the U.S. Wage Structure</em> paper. All the relevant files to replicate the paper are publicly available on <a target="_blank" rel="nofollow" href="http://economics.mit.edu/faculty/angrist/data1/data/angchefer06"><em>Angrist’s Data Archive</em></a></p>
<p>Files are in Stata format, so I use the <code>foreign</code> package to read the data set corresponding to the 2000 census. The data set is quite large, it contains 97397 observations and 5 variables: the logarithm of wage, education, race, experience and experience squared.</p>
<div>
<pre><code><span>require</span><span>(</span><span>foreign</span><span>)</span><span>
</span></code></pre>
</div>
<div>
<pre><code>Loading required package: foreign
</code></pre>
</div>
<div>
<pre><code><span>dta</span><span>&lt;-</span><span>read.dta</span><span>(</span><span> </span><span>&quot;~/Data/census00.dta&quot;</span><span>)</span><span>
</span><span>y</span><span>&lt;-</span><span>dta</span><span>$</span><span>logwk</span><span>
</span><span>X</span><span>&lt;-</span><span>cbind</span><span>(</span><span>rep</span><span>(</span><span>1</span><span>,</span><span>length</span><span>(</span><span>y</span><span>)),</span><span>dta</span><span>$</span><span>educ</span><span>,</span><span>dta</span><span>$</span><span>black</span><span>,</span><span>dta</span><span>$</span><span>exper</span><span>,</span><span>dta</span><span>$</span><span>exper2</span><span>)</span><span>
</span><span>dim</span><span>(</span><span>X</span><span>)</span><span>
</span></code></pre>
</div>
<div>
<pre><code>[1] 97397     5
</code></pre>
</div>
<p>We focus here on the dual problem, and focus only on the returns to schooling for five quantiles: .10, .25, .50, .75 and .90, and also the Mean Estimate using OLS</p>
<div>
<pre><code><span>-</span><span>qr.mosek.dual</span><span>(</span><span>X</span><span>,</span><span>y</span><span>,</span><span>tau</span><span>=</span><span>.1</span><span>)</span><span>$</span><span>sol</span><span>$</span><span>itr</span><span>$</span><span>suc</span><span>[</span><span>2</span><span>]</span><span>
</span></code></pre>
</div>
<div>
<pre><code>[1] 0.09090798
</code></pre>
</div>
<div>
<pre><code><span>-</span><span>qr.mosek.dual</span><span>(</span><span>X</span><span>,</span><span>y</span><span>,</span><span>tau</span><span>=</span><span>.25</span><span>)</span><span>$</span><span>sol</span><span>$</span><span>itr</span><span>$</span><span>suc</span><span>[</span><span>2</span><span>]</span><span>
</span></code></pre>
</div>
<div>
<pre><code>[1] 0.1033592
</code></pre>
</div>
<div>
<pre><code><span>-</span><span>qr.mosek.dual</span><span>(</span><span>X</span><span>,</span><span>y</span><span>,</span><span>tau</span><span>=</span><span>.5</span><span>)</span><span>$</span><span>sol</span><span>$</span><span>itr</span><span>$</span><span>suc</span><span>[</span><span>2</span><span>]</span><span>
</span></code></pre>
</div>
<div>
<pre><code>[1] 0.1110223
</code></pre>
</div>
<div>
<pre><code><span>-</span><span>qr.mosek.dual</span><span>(</span><span>X</span><span>,</span><span>y</span><span>,</span><span>tau</span><span>=</span><span>.75</span><span>)</span><span>$</span><span>sol</span><span>$</span><span>itr</span><span>$</span><span>suc</span><span>[</span><span>2</span><span>]</span><span>
</span></code></pre>
</div>
<div>
<pre><code>[1] 0.1215066
</code></pre>
</div>
<div>
<pre><code><span>-</span><span>qr.mosek.dual</span><span>(</span><span>X</span><span>,</span><span>y</span><span>,</span><span>tau</span><span>=</span><span>.9</span><span>)</span><span>$</span><span>sol</span><span>$</span><span>itr</span><span>$</span><span>suc</span><span>[</span><span>2</span><span>]</span><span>
</span></code></pre>
</div>
<div>
<pre><code>[1] 0.1549263
</code></pre>
</div>
<div>
<pre><code><span>solve.ols</span><span>(</span><span>X</span><span>,</span><span>y</span><span>)</span><span>$</span><span>sol</span><span>$</span><span>itr</span><span>$</span><span>xx</span><span>[</span><span>2</span><span>]</span><span>
</span></code></pre>
</div>
<div>
<pre><code>[1] 0.1148
</code></pre>
</div>
<p>It interesting how the average return is about 11 but when we focus on the quantiles a different pattern emerges. The mean and median returns are quite similar but larger returns to schooling appear as we move to the upper quantiles. I could not end this incursion into Mosek without comparing computation times for the application.</p>
<div>
<pre><code><span>tau</span><span>&lt;</span><span>-0.5</span><span>
</span><span>microbenchmark</span><span>::</span><span>microbenchmark</span><span>(</span><span>
</span><span>qr.mosek.dual</span><span>(</span><span>X</span><span>,</span><span>y</span><span>,</span><span>tau</span><span>=</span><span>tau</span><span>),</span><span>
</span><span>rq.fit.br</span><span>(</span><span>X</span><span>,</span><span>y</span><span>,</span><span>tau</span><span>=</span><span>tau</span><span>)</span><span>
</span><span>)</span><span>
</span></code></pre>
</div>
<div>
<pre><code>Unit: milliseconds
                           expr       min        lq      mean    median
 qr.mosek.dual(X, y, tau = tau)  420.2002  434.9739  473.0457  456.4372
     rq.fit.br(X, y, tau = tau) 4642.0985 4761.6424 5034.9789 5052.8138
        uq       max neval
  472.2065  889.6079   100
 5226.3060 5975.6663   100
</code></pre>
</div>
<p>Mosek now turns to be considerable faster than <code>rq</code>. Thus, for a moderately large problem and using the dual formulation of the quantile program <em>Mosek</em> performs quite well.</p>
<p>To finish, those interested in convex optimization with R I would recommend reading the paper by Koenker and Mizera (2014) <a target="_blank" rel="nofollow" href="http://www.econ.uiuc.edu/~roger/research/conopt/coptr.pdf">Convex Optimization in R</a>.</p>
<p><strong>Comments and suggestions are always welcomed. You can send them to <code>srmntbr2</code> at <code>illinois.edu</code>.</strong></p>
<h2>References and Further Readings</h2>
<p>Angrist, J., Chernozhukov, V., &amp; Fernández‐Val, I. (2006). Quantile regression under misspecification, with an application to the US wage structure. Econometrica, 74(2), 539-563.</p>
<p>Angrist, J. D., &amp; Pischke, J. S. (2008). Mostly harmless econometrics: An empiricist’s companion. Princeton university press.</p>
<p>Friberg HA (2014). Rmosek: The R-to-MOSEK Optimization Interface. R package version 1.2.5.1, URL <a target="_blank" rel="nofollow" href="http://cran.r-project.org/package=Rmosek">http://CRAN.R-project.org/package=Rmosek</a>.</p>
<p>Koenker, R. (2005). Quantile regression. No. 38. Cambridge university press.</p>
<p>Koenker, R. (2016). quantreg: QuantileRegression. R package version 5.29. <a target="_blank" rel="nofollow" href="https://cran.r-project.org/package=quantreg">https://CRAN.R-project.org/package=quantreg</a></p>
<p>Koenker, R., &amp; Hallock, K. (2001). Quantile regression: An introduction. Journal of Economic Perspectives, 15(4), 43-56.</p>
<p>Koenker, R., &amp; Mizera, I (2014). “Convex optimization in R.” Journal of Statistical Software 60, no. 5: 1-23.</p>
<p>MOSEK ApS, Denmark (2011). The MOSEK Optimization Tools Manual. Version 6.0, <a target="_blank" rel="nofollow" href="http://www.mosek.com/">http://www.mosek.com/</a>.</p>
<p>
<div>
<div>To <strong>leave a comment</strong> for the author, please follow the link and comment on their blog: <strong><a href="https://ignaciomsarmiento.github.io/2017/01/20/Quantile-and-OLS-Regression-with-Rmosek.html"> Ignacio Sarmiento Barbieri</a></strong>.</div>
<hr>
<a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers.com</a> offers <strong><a rel="nofollow" href="https://feedburner.google.com/fb/a/mailverify?uri=RBloggers">daily e-mail updates</a></strong> about <a title="The R Project for Statistical Computing" rel="nofollow" href="https://www.r-project.org/">R</a> news and <a title="R tutorials" rel="nofollow" href="https://www.r-bloggers.com/search/tutorial">tutorials</a> on topics such as: <a title="Data science" rel="nofollow" href="https://www.r-bloggers.com/search/data%20science">Data science</a>, <a title="Big Data" rel="nofollow" href="https://www.r-bloggers.com/search/Big%20Data">Big Data, <a title="R jobs" rel="nofollow" href="https://www.r-users.com/">R jobs</a>, visualization (<a title="ggplot and ggplot2 tutorials" rel="nofollow" href="https://www.r-bloggers.com/search/ggplot2">ggplot2</a>, <a title="Boxplots using lattice and ggplot2 tutorials" rel="nofollow" href="https://www.r-bloggers.com/search/boxplot">Boxplots</a>, <a title="Maps and gis" rel="nofollow" href="https://www.r-bloggers.com/search/map">maps</a>, <a title="Animation in R" rel="nofollow" href="https://www.r-bloggers.com/search/animation">animation</a>), programming (<a title="RStudio IDE for R" rel="nofollow" href="https://www.r-bloggers.com/search/RStudio">RStudio</a>, <a title="Sweave and literate programming" rel="nofollow" href="https://www.r-bloggers.com/search/sweave">Sweave</a>, <a title="LaTeX in R" rel="nofollow" href="https://www.r-bloggers.com/search/LaTeX">LaTeX</a>, <a title="SQL and databases" rel="nofollow" href="https://www.r-bloggers.com/search/SQL">SQL</a>, <a title="Eclipse IDE for R" rel="nofollow" href="https://www.r-bloggers.com/search/eclipse">Eclipse</a>, <a title="git and github, Version Control System" rel="nofollow" href="https://www.r-bloggers.com/search/git">git</a>, <a title="Large data in R using Hadoop" rel="nofollow" href="https://www.r-bloggers.com/search/hadoop">hadoop</a>, <a title="Web Scraping of google, facebook, yahoo, twitter and more using R" rel="nofollow" href="https://www.r-bloggers.com/search/Web+Scraping">Web Scraping</a>) statistics (<a title="Regressions and ANOVA analysis tutorials" rel="nofollow" href="https://www.r-bloggers.com/search/regression">regression</a>, <a title="principal component analysis tutorial" rel="nofollow" href="https://www.r-bloggers.com/search/PCA">PCA</a>, <a title="Time series" rel="nofollow" href="https://www.r-bloggers.com/search/time+series">time series</a>, <a title="finance trading" rel="nofollow" href="https://www.r-bloggers.com/search/trading">trading</a>) and more...
<img height="1" alt="" width="1" src="http://feeds.feedburner.com/~r/RBloggers/~4/gf2Ifvcxk50"></a></div>