Showing posts with label Python. Show all posts
Showing posts with label Python. Show all posts

Wednesday, May 22, 2024

MOSEK 10.2 and Pythonic Fusion API

MOSEK 10.2 introduces a feature that we hope will be interesting for all users of our Python Fusion API, which we call Pythonic Fusion. 

Pythonic Fusion is an overlay on top of the current Fusion API (or, as some would call it, syntactic sugar) which implements standard Python operators for Fusion objects (variables, parameters, expressions). There are operators for manipulating linear expressions:

+, -, *, @, [:], .T

relational operators for introducing constraints:

==, <=, >=

and operators for introducing AND- and OR-clauses in disjunctive constraints:

&, |

The operators are used in the most natural way familiar from NumPy, CVXPY, Pandas or any other data processing tool in Python, so we restrict to giving a simple example. The following Python Fusion constraint

M.constraint(Expr.mul(G, Expr.sub(x.transpose(), y.slice(0, n))),                          Domain.lessThan(c))

will be written in Pythonic Fusion as

M.constraint(G @ (x.T - y[:n]) <= c)

A more comprehensive introduction to the new syntax can be found in the manual. Examples using Pythonic Fusion are scattered throughout the manual, in particular in the portfolio optimization case study, and with time we will adapt our other Python Fusion resources to the new syntax. You are welcome to share your suggestions, comments or bug reports with us.

Important. In MOSEK 10.2 Pythonic Fusion is a separate add-on, available only after importing:

import mosek.fusion.pythonic


Monday, December 14, 2020

MOSEK in the browser and OptServer

Although both installing MOSEK and obtaining a trial license are very easy, it is now possible to get to know MOSEK directly in the browser with one click and no setup at all.

Python

With a Google account you can run MOSEK in Google Colab notebooks. Click below to open the sample MOSEK Colab notebook in your user space and run it.


(You can also just download the notebook and run it in Jupyter or your favorite environment, but that's more than one click). Since this is a complete MOSEK installation in Python, the full Optimizer and Fusion APIs are available.

Javascript Fusion

The Fusion API is experimentally available in Javascript. Just click below to open the editor in the browser and start coding and solving optimization problems in our Fusion API.


An almost complete Fusion API is mapped through and you can run a number of ready examples.

How does it work?

The key to the simplicity lies in the fact that the actual optimizations are performed on our freely available demo Optimization Server (OptServer) running at https://solve.mosek.com. On that page you can also find instructions for invoking remote optimization in all other MOSEK interfaces; that's how the Python notebooks calls the OptServer. The Javascript package runs the Fusion layer modeling in the browser and sends a JSON task object for remote optimization.

Our online demo server has problem size limits. If you like the concept of remote optimization it is almost as easy as this to set up your own demo OptServer in a docker container and use that to optimize.

Monday, June 6, 2016

Improving Python API performance

Recently a MOSEK user pointed out out that sometimes the MOSEK Python API can be quite slow when it comes to input large amount of data. In particular the problem is related to the way MOSEK handles 32 and 64 bit integers.


If you use Numpy with a 64-bit Python, integer arrays will usually end up being arrays of numpy.int64 since the native Python integer is an int64.


Most MOSEK functions require arrays of numpy.int32, e.g. for variable or constraint indexing. In this case it can often significantly speed up the function call to explicitly convert the types.

To this extent is worth using numpy.array class to convert arrays of indexes to the right size: the numpy implementation is highly efficient and saves a lot of time!

Tests

To show the performance gain in Python 2.7 we implement a simple tests involving
  • n=1000000 variables,
  • linear objective function terms and
  • quadratic objective function terms.
using Python timeit module. Each tests is repeated num=100 times and we removed from the timing unecessart contributions such as module import and task/environment declaration.

Note we show source code without timeit instrumentation to keep it simple. 

The complete testing code is available at the end of the post.

Objective function linear coefficents.

Say we want to input the coefficients for n variables in the objective function. We can do it using Python arrays or  numpy arrays instead. The code to time the running time is


We obtain the following results


  • direct input: 1.113329s
  • using numpy : 0.017299s


Objective function quadratic coefficients.

Say we want to input the coefficients of the linear part of the objective function. The benchmark code is



It provides the following results


  • direct input: 2.239344s
  • using numpy : 0.028208s


Conclusion

The MOSEK Python API converts by default 64bit integers to 32 bit ones, and this operation could introduce significant overhead. Using numpy array to convert integer arrays to 32 bit is a simple simple workaround that allows to speed up the input process significantly. 

The improvement is quite remarkable. However, it must be noticed that not all users will experience such an improvement. Nevertheless it is a good idea to check your code and see whether you can gain some performance.

Remember that this issue is solved in the new MOSEK 8 release.


Complete code



Monday, March 16, 2015

Machine Learning with MOSEK Fusion: linear soft-margin Support Vector Machine

Machine-Learning (ML)  has become a common widespread tool in many applications that affect our everyday life. In many cases, at the very core of these techniques there is an optimization problem. In this post we will show how one of the most common ML technique, the Support-Vector Machine (SVM) is defined as the solution of a conic optimization problem.

The aim of this post is two-fold:
  1. To show that simple SVM models can be efficiently solved with a commercial general-purpose solver as MOSEK
  2. That the MOSEK Fusion API yield  a very compact and expressive code.
We are not claiming that a general-purpose solver is the tool of choice for solving SVMs problems. There is a huge literature about specialized algorithms, and software packages (see for instance LibSVM) that exploit their peculiar structure. 

In words, the basic SVM model can be stated as:
"We are given a set of points $m$ in a $n$-dimensional space, partitioned in two groups. Find, if any, the separating hyperplane of the two subsets with the largest margin, i.e. as far as possible from the points."

In mathematical form, that means to determine an hypeplane $w^T x = b$ that separate  two sets of points leaving the largest margin possible. It can be proved that the margin is given by $2/\|w\|$.

Therefore, we need to solve the problem of maximizing  $2/\|w\|$ with respect of $w,b$ with the constraints that points of the same class must lie on the same side of the hyperplane. Denoting with $x_i\in\mathbb{R}^n$ the i-th observation and assuming that each point is given a label $y_i\in \{-1,+1\}$, it is easy to see that the separation is equivalent to:

\[
     y_i (w^T x_i -b)\geq 1.
\]

A simple example in two dimension is the following:



It is easy to show (see [1]) that the separating hyperplane is the solution of the following optimization problem:

\[
\begin{array} {lll}
\min & \frac{1}{2} \| w \|^2  &\\
& y_i (w^T x_i -b ) \geq 1& i=1,\ldots,m
\end{array}
\]

If a solution exists, $w,b$ define the separating hyperplane and the sign of $w^Tx -b$ can be used to decide the class in which a point $x$ falls.

To allow more flexibility the soft-margin SVM classifier is often used instead. It allows for violation of the classification. To this extent a non-negative slack variable is added to each linear constraint and penalized in the objective function.

\[
\begin{array} {lll}
\min_{b,w} & \frac{1}{2} \| w \|^2  + C \sum_{i=1}^{m} \xi_i&\\
& y_i (w^T x_i -b ) \geq 1 - \xi_ i& i=1,\ldots,m\\
& \xi_i \geq 0 & i=1,\ldots,m
\end{array}
\]

In matrix form we have 

\[
\begin{array} {lll}
\min_{b, w, \xi} & \frac{1}{2} \| w \|^2  + C \mathbf{e}^T \xi\\
&    y \star ( X w - b \mathbf{e})  + \xi \geq \mathbf{e}\\
& \xi \geq 0
\end{array}
\]

where $\star$ denotes the component-wise product, and $\mathbf{e}$ a vector with all components equal to one. The constant $C>0$ acts both as scaling factor and as weight. Varying $C$ yields different trade-off between accuracy and robustness.

Implementing the matrix formulation of the soft-margin SVM in Fusion is very easy. We only need to cast the problem in conic form, which in this case only involves converting the quadratic term of the objective function in a conic constraint:


\[
\begin{array} {ll}
\min_{b, w, \xi,t} & t  + C \mathbf{e}^T \xi& \\
&    \xi + y \star ( X w - b \mathbf{e})  \geq \mathbf{e}\\
& (1,t,w) \in \mathcal{Q_r}^{n+2}\\
& \xi \geq 0
\end{array}
\]

where $\mathcal{Q_r}$ denotes a rotated cone of dimension $n+2$.

In our Fusion implementation we will allow the user to specify a set of values for $C$, and we will solve a problem for each one. We will show Python code for sake of simplicity. However, much better performance can be achieved with the Java or C# API.

Let assume now we are given an array y of labels, a matrix X where input data are stored row-wise and a set of values C for  we want to test. The implementation in Fusion of our conic model is the following



The code is so expressive that it deserves very few comments:


  1.  A sequence of problem can be solved just changing the objective function, as in loop starting in line 19: in this most of the model is build only once.
  2. Expression in line 13 shows how a linear expression can be store and reused.
  3. The construct Variable.repeat(b,m)  logically repeats variable $b$, i.e. forms an array of the form $(b,b,b,\ldots,b)^T \in \mathbb{R}^m$.
  4. The solution is recovered by the level method: if an optimal solution hasn't been found, an exception is thrown.

Let's make few tests. We generate two sets of random two dimensional points each from a Gaussian distribution: the first set centered at $(1.0,1.0)$; the second at $(-1.0,-1.0)$. We experiment standard deviation $\sigma$ of $1/2$ and $1$.

With $\sigma=1/2$ we obtain a separable sets of points and for $C=1$ we have  the following




For $\sigma=1$ separability is usually not possible. Larger value of $C$ emphasize good classification, but reduces the margin and hence robustness. For instance, we may obtain the following:



The black and red lines correspond to $C=1$ and $C=2^{10}$.

MOSEK solves this problems in almost no time:





Further improvements can be obtained exploiting sparsity: in most cases input data are supposed to be sparse, i.e. most entries in the X matrix are zero. If this is the case, then Fusion, and therefore MOSEK, can exploit such a property. You only need to feed the function with a Fusion sparse matrix:



where Xi,Xj,Xv are the arrays that store the sparse representation of X in triplet form. This will save memory and reduce the computational burden.


So to summarize: you can easily build your own linear SVM classifier with MOSEK Fusion! Give it a try and play with it. Fusion demonstrates again its simplicity and power of expressiveness.

[1] Cortes, Corinna, and Vladimir Vapnik. "Support-vector networks." Machine learning 20.3 (1995): 273-297.

Wednesday, March 14, 2012

Portfolio optimization whitepaper in MATLAB, R and Python

We revised our whitepaper on portfolio optimization.

The whitepaper gives an introduction to portfolio optimization using the MOSEK conic optimizer from MATLAB, R and Python and includes topics such as:
  • Conic formulations of standard Markowitz portfolio problems.
  • Minimum risk/maximum return formulations.
  • Computing the efficient frontier.
  • Computing the maximum Sharpe ratio.
  • Exploiting low-rank structure in the covariance matrix to reduce solution time, including factor models.
  • Transaction costs with market impact, modeled as a conic quadratic problem.
  • Transactions costs with a fixed term, modeled as a conic mixed-integer problem. 
Historical data from the S&P500 index is used in all examples.

The Markowitz portfolio optimization whitepaper and data can be downloaded from the MOSEK publications page.