CodeNewbie Community 🌱

Cover image for Creating an ML Model and Serving it as a RESTful API: Part 1
Andrea Gonzales
Andrea Gonzales

Posted on

Creating an ML Model and Serving it as a RESTful API: Part 1

I started my internship at a local company that focuses on Data Science and Machine Learning and as part of my training, I was tasked to create a simple Iris Classification model that identifies the type of Iris category (Versicolor, Virginica and Setosa) based on the given petal and sepal width and length. Being someone who has minimal Machine Learning background, I needed a lot of research and reading in order to arrive at the required output, but it was all worth it.

Iris

In this post, I will be sharing the steps I did to create an Iris Classification model using Python and serve it through Flask RESTful API. I have also created a simple PHP interface that connects to the API to demonstrate its usage.

Model Creation 🤖

In Machine Learning, a model is trained using a set of data to recognize certain patterns. Python's open-source Machine Learning library, Sci-Kit Learn, provides model training for supervised and unsupervised learning. It is simple to use and it has a lot of tutorials to get started with.

First, install Sci-Kit library using pip:

pip install -U scikit-learn
Enter fullscreen mode Exit fullscreen mode

Once the installation is finished, create a file called model.py where Sci-Kit Learn's already made Iris dataset can be used:

from sklearn import datasets
iris = datasets.load_iris()
Enter fullscreen mode Exit fullscreen mode

Note: You can use your own dataset but it needs to be preprocessed and formatted for Sci-Kit Learn to understand and train the model as efficiently as possible.

Next, the datasets are separated into data and target. Data consists of petal and sepal width and length in centimetres, while the target, or the label, is the class to predict. For the Iris classification, the target consists of versicolor, virginica and setosa.

iris_data = iris.data
iris_target = iris.target
Enter fullscreen mode Exit fullscreen mode

Before training the model, the data and target are split again so that the other half is used for the actual model training while the other is used for verifying the model (in other terms, testing the model's accuracy).

This can be achieved using train_test_split:

from sklearn.model_selection import train_test_split
iris_data_train, iris_data_test, iris_target_train, iris_target_test = train_test_split(iris_data, iris_target, test_size = .5)
Enter fullscreen mode Exit fullscreen mode

The test_size parameter specifies the size of the testing datasets.

Now, we can start building the model. There are many classification algorithms that can be used for this model, but I settled on K-Nearest Neighbors as the accuracy score is much higher.

from sklearn import neighbors
classifier = neighbors.KNeighborsClassifier()
Enter fullscreen mode Exit fullscreen mode

From this, we can start training the model:

classifier.fit(iris_data_train, iris_target_train)
Enter fullscreen mode Exit fullscreen mode

And there we have it! We have a trained Iris classification model. We can print the accuracy level of the model using accuracy_score:

from sklearn.metrics import accuracy_score
predict_iris = classifier.predict(iris_data_test)
print(accuracy_score(iris_target_test, predict_iris))
Enter fullscreen mode Exit fullscreen mode

From the above, the model has an accuracy score of 97%! Great!

Creating Flask API ⚙️

Before we create the Flask API, the model needs to be serialized using a Python library called Pickle. By "pickling" a python code, it is converted into a byte stream for it to be easily sent over the network or saved on disk. "Unpickling" is the opposite, where it converts the python file into its original state.

Pickle

Pickle can be installed using pip:

pip install pickle-mixin
Enter fullscreen mode Exit fullscreen mode

Our Iris classification model can be "pickled" or serialized using the following code:

import pickle
pickle.dump(classifier, open("iris_model", "wb"))
Enter fullscreen mode Exit fullscreen mode

This creates the iris_model file. If you try to open it, it will show indecipherable characters.

Now that we have our model pickled, we can now start with the Flask API!

Like the rest of the Python libraries, we install flask as well:

pip install flask
Enter fullscreen mode Exit fullscreen mode

We then create our main app file called app.py. Inside, we import the libraries required for our Flask API:

from flask import Flask, jsonify
from flask_restful import reqparse, abort, Api, Resource

app = Flask(__name__)
api = Api(app)
Enter fullscreen mode Exit fullscreen mode

Our Iris Classification model is then loaded and "unpickled":

import pickle
loaded_model = pickle.load(open("iris_model", 'rb'))
Enter fullscreen mode Exit fullscreen mode

When we create the front-end interface later, we need a way to send over the user input to the Iris classification Flask API. In order to do that, we create parameters to the URL and we pass the user input there. The inputs we need are the petal and sepal width and length, and from this information, the model predicts what type of Iris flower we are referring to.

We create the parameters using the following code:

parser = reqparse.RequestParser()
parser.add_argument('slength')
parser.add_argument('swidth')
parser.add_argument('plength')
parser.add_argument('pwidth')
Enter fullscreen mode Exit fullscreen mode

Once the queries are set, we need to call the model to predict the Iris type based on the given inputs. We then create a class called requestIris that takes the URL parameter values then insert it to the model for prediction. The predictions will come into integer format, so 0 is setosa, 1 is versicolor, and 2 is virginica. Also, note that the data returned should be in JSON format.

The full code is stated below:

class requestIris(Resource):
    def get(self):
        args = parser.parse_args()
        slength= args['slength']
        swidth = args["swidth"]
        plength = args["plength"]
        pwidth = args["pwidth"]
        prediction = (loaded_model.predict([[slength, swidth, plength, pwidth]])).tolist()
        if(prediction[0] == 0):
            type="setosa"
        elif(prediction[0] == 1):
            type="versicolor"
        else:
            type="virginica"
        serve_model = {"Iris Type":type}
        print(serve_model)
        return jsonify(serve_model)
Enter fullscreen mode Exit fullscreen mode

We then add the resource to our API, and create a route for the resource:

api.add_resource(requestIris, '/classify')
Enter fullscreen mode Exit fullscreen mode

Last but not least, we add the code to run our Flask application:

if __name__ == '__main__':
   app.run()
Enter fullscreen mode Exit fullscreen mode

Hurray! We have our Iris Classification API now!

The API can be run locally or published to Heroku. I published mine here:

https://iris-classification-model.herokuapp.com/

In the next post, I will be writing about the PHP frontend interface to demonstrate the API's application. Stay tuned!

Top comments (0)