Machine Learning Implementation using Java and Tribuo

Creating a REST Service for Wine Quality Prediction using Tribuo and SpringBoot

This is the concluding post in a series of four posts.


In the previous post, Going Deeper with Tribuo, we created a Random Forest model that was trained to predict the quality of red wine based on the values of eleven given characteristics. This time, we will use this model to create a REST service that will respond with a prediction of the wine quality when sent a request containing the values of the wine characteristics.

Prediction as a REST Service

A common way to deploy a Machine Learning model is ‘wrapping’ it with a REST service that accepts prediction requests and returns the corresponding prediction results. Each request contains the values of the model inputs (‘features’) that are in turn fed to the model to produce the prediction. This setup is sometimes referred to as a ‘Model Server‘.

In the previous post, Going Deeper with Tribuo, we have trained a regressor to provide wine quality predictions based on eleven characteristics, using the UCI Wine Quality Dataset and then saved the model to a file. We can now create an application that will load that model back from the file, and wrap it with a REST service as shown in the image above.

Implementation

A popular way to implement a Java-based standalone REST service is enlisting the help of the SpringBoot framework, and using its REST service example as a starting point.

The Code for our wine-predicting project resides in this Github repository.

Maven Setup

As our code is setup as a Maven project, we will start by adding the necessary SpringBoot portions to the pom.xml. We start with including the definition of the SpringBoot starter-parent pom:

Then adding the starter-web dependency:

and finally adding the appropriate Maven plugin:

The class files we will be using for this service reside in the service folder.

Helper Files

The class RestServiceApplication is used to configure and launch our program as a SpringBoot application. Behind the scenes, the @SpringBootApplication annotation creates various needed configurations.

The classes WineQualityPredictionRequest and WineQualityPredictionResult are essentially plain Java objects, encapsulating the contents of the REST request and response, respectively.

The class WineQualityPredictionRequest contains eleven data members, representing the values of the inputs (or features) of the model:

The getFeatureValues() method returns an array with the values of these members, to be consumed by the model:

In addition, this class holds a list with the matching names of the features, also to be used by the model:

The class WineQualityPredictionResult contains a single value—quality—representing the prediction result:

REST Controller

The heavy lifting of this application takes place at the WineQualityPredictionController class. The annotations at the top turn this class into a REST service that responds to requests with a path starting with “/predict“:

The constructor of the class calls the loadModel() method, which reads the file containing the model’s data, that was saved when we ran the WineQualityRegression class in the previous post:

Tribuo’s Model class enables us to validate the correct output type of the model after uploading it from the file:

We can go a step further and examine the provenance of the training algorithm as well as the dataset that was used for the training:

The resulting output is identical to that of the trained model that we saw in the previous post before saving it to the file:

The predictQuality() method is the one handling the actual regression request, a POST request with the path /predict/wineQuality. As the method’s signature suggests, the body of the request is expected to carry a JSON payload that will be mapped to the an object of the type WineQualityPredictionRequest:

Now that we have a request object containing the features’ names and values, we have one additional step left before we can ‘feed’ it into the model: in Tribuo, models expect the type Example as input for for their predict() method. To create this Example object, we start by defining an empty, ‘placeholder’ output object, that will be used to contain the prediction result. We then create the Example object of the concrete type ArrayExample using the output placeholder, the (constant) array of feature names and the corresponding array of feature values that came in with the request:

The next step is to provide this example to the model, which in turn yields the prediction, and then extract the value of the output. As we mentioned before, Tribuo regressors support a multi-value output,  however in our case there is a single output valuethe wine quality—contained in the first element of the output array:

Lastly, we create an object of the type WineQualityPredictionResult using the prediction result. This object will be mapped into a JSON payload by our controller and placed in the body of the REST response message:

Testing The REST Service

We are now ready to run the application and test our service.

When launching the application via the main() method of the class RestServiceApplication, we will first see SpringBoot’s familiar banner:

This will be followed by the output of the dataset and trainer provenance that we mentioned above, and will finally display output similar to the following:

We can now send a prediction request to the application. One common way of sending REST requests is using the application Postman REST Client,enabling us to setup a POST message with the path http://localhost:8080/predict/wineQuality, and a body containing a JSON object with the values of the features as shown in this example:

 

The values for this sample request were taken from the last row of the dataset. The matching quality value for this row is 6, as seen at the end of the row.

When we send the request, we get the following response, with a prediction value of 6.2:

Another way to send REST requests is using the ubiquitous command-line utility curl from a terminal or a command window:

The returned response is shown below:

What’s Next?

You can now extend this REST controller in various ways, for example:

  • Return classification results for wine quality using the classifier we created in our First Tribuo Example post
  • Return regression and/or classification results for white wine quality using the white wine dataset
  • Create additional classifier and regressor models based on various other algorithms (e.g. SVM)

This post concludes our series of Machine Learning Implementation using Java and Tribuo. There is a lot more to Tribuo, and I encourage you to explore it further using the available documentation, the Jupyter notebooks-based tutorials and the source code available at GitHub.

Tagged , , , , , , , , , , , , ,

About Eyal Wirsansky

Eyal Wirsansky is a senior software developer, an artificial intelligence consultant and a genetic algorithms specialist, helping developers and startup companies learn and utilize artificial intelligence techniques. Eyal is the author of the book 'Hands-On Genetic Algorithms with Python' (Packt).
View all posts by Eyal Wirsansky →

Leave a Reply

Your email address will not be published. Required fields are marked *