Building an accurate machine learning (ML) model is a feat on its own. But once you’re there, you still need to find a way to make the model accessible to users. If you want to create a GUI for it, the obvious approach is going after shiny. However, often you don’t want a direct GUI for a ML model but you want to integrate the logic you’ve created into an existing (or new) application things become a bit more difficult.

Let’s say you’ve created a robust ML model in R and explain the model to your in-house IT department, it is (currently) definitely not a given that they can easily integrate it. Be it either due to the technology used is unfamiliar to them or because they simply don’t have a in-depth knowledge on ML.

There are a lot of way to go about this. One way (and the focus of this post) is to built a sort of “black-box” model which is accessible through a web-based API. The advantage of this is that a web call can be very easily made from (almost) any programming language, making integration of the ML model quite easy.

Below an example ML model is made accessible by using Jug (disclaimer: I’m the author of Jug :).

### Training the model

We start by creating a very simple model based on the mtcars dataset and the randomForest package (don’t interpret this as the way to correctly train a model). This model is then saved to the file system.

The model tries to predict mpg based on the disp, wt and hp variables.

The summary of the resulting model:


Call:
randomForest(formula = mpg ~ disp + wt + hp, data = mtcars)
Type of random forest: regression
Number of trees: 500
No. of variables tried at each split: 1

Mean of squared residuals: 5.421786
% Var explained: 84.59


### Setting up the API

For setting up the API we use Jug.

Serving the jug at http://127.0.0.1:8080


So, what does this code do? The mpg_fit holds the fitted ML model. The predict_mpg function uses this model and returns a predicted value based on the received disp, wt and hp parameters.

The part starting with jug() %>% configures and launches the API. If it receives a post request at the /mpg_api path (with the requested parameters) it returns the result of decorate(predict_mpg) to the post call.

The decorate function is basically a convenience function which maps the supplied parameters (form-data, url-encoded, …) to the function you supply it. The error handler is simply there to avoid the server crashing when it gets called with an unbound path/erroneous data.

The serve_it() call launches the API instance.

### Calling the API

The result is that we now have a live web-based API. We can post data to it and get back a predicted value. Below an example post call using curl.

curl -s --data "disp=160&wt=2620&hp=110" http://127.0.0.1:8080/mpg_api

>> 18.9758366666667


This R app can then be launched on a server which in turn can receive post calls from any type of application which can make web calls.

### Other packages

Also have a look at the base httpuv package (which is the basis for Jug) and the more applied prairie (previously known as dull) and plumber packages.