Deploying Machine Learning Models using Flask

January 16, 2021

In this article, we will learn about deploying Machine Learning models using Flask. By the end of the article, you will have an overview of how Machine Learning models are built, how Flask servers interact with our Machine Learning model, and how to connect the model with a web application. You will also learn a step-by-step procedure for deploying the model locally.

I highly recommend going over this article to better grasp those concepts regarding Flask. As a prerequisite, a little knowledge about HTML and CSS would help to follow this article along.

Table of contents

Step by step guide for implementation

Objective

In this tutorial, we are going to deploy a simple Machine Learning model using the Flask webserver. As a demonstration, our Machine Learning model will helps us classify the variety of flowers based on the length and width of sepals and petals. We will build a simple HTML webpage to accept the measurements as input and classify the variety based on the classification model.

Machine Learning Model

Dataset

When building the Machine Learning model, we will make use of the Iris dataset.

A glimpse of the data is as shown below:

A few rows of Iris dataset

Classification Model

Having chosen the dataset, it’s time to build our classification model. Let’s name the file model.py.

First, we import the necessary Python libraries for building the classification model.

Here, we use the following libraries:

  • Pandas.

  • Numpy.

  • Sklearn/Sci-kit learn,

# Importing necessary libraries
import pandas as pd # To manage data as data frames
import numpy as np # To manipulate data as arrays
from sklearn.linear_model import LogisticRegression # Classification model

After importing the libraries, we import the dataset using pd.read_csv command. This command reads the CSV file and transforms it into a data frame called data. Generally, working with data frames is much easier when compared to that of arrays.

The CSV file of the dataset can be downloaded here and saved in the same working directory of model.py.

# Importing the dataset
data = pd.read_csv('./iris.csv')

Iris dataset

As you see in the image, the target variable under the variety column has textual data. Since the textual data is made use of in building our Machine Learning model, we must encode the textual data as numbers.

For example, let’s say, we map the flower variety Setosa as 0, Versicolor as 1, and Virginica as 2. In the data frame data, we replace the textual data with respective numbers, based on the above mapping.

# Dictionary containing the mapping
variety_mappings = {0: 'Setosa', 1: 'Versicolor', 2: 'Virginica'}

# Encoding the target variables to integers
data = data.replace(['Setosa', 'Versicolor' , 'Virginica'], [0, 1, 2])

Having replaced the textual data, we can get started with building the actual classification model.

First, we have to separate the independent values (features) from the dependent values (target). To do this, we make use of the .iloc[] method to slice the rows and columns of the data frame.

X = data.iloc[:, 0:-1] # Extracting the features/independent variables
y = data.iloc[:, -1] # Extracting the target/dependent variable

In the above snippet, for features columns X, we consider all the columns from 0 to the last, but one. Here, -1 signifies that we exclude the last column.

Similarly, for target column y, we consider only the last column.

logreg = LogisticRegression(max_iter=1000) # Initializing the Logistic Regression model
logreg.fit(X, y) # Fitting the model

Next, we initialize the LogisticRegression() model by calling and creating a Python object and assigning it to a variable called logreg.

Finally, we fit the features X with the target values y. This can be done, by making use of .fit() function.

# Function for classification based on inputs
def classify(a, b, c, d):
    arr = np.array([a, b, c, d]) # Convert to numpy array
    arr = arr.astype(np.float64) # Change the data type to float
    query = arr.reshape(1, -1) # Reshape the array
    prediction = variety_mappings[logreg.predict(query)[0]] # Retrieve from dictionary
    return prediction # Return the prediction

To modularize the code, we build a method called classify() to return the predictions based on the input arguments passed. In this function, we accept the length and the width of both sepal and petal as input arguments. Then, we make a numpy array using np.array(), convert the data type from string to float, and reshape the array by finding the transpose.

Now, our Logistic regression model classifies the variety based on the above-pre-processed input. The probability score predicted using logistic regression can be used when finding the right mapping to the name of variety, using a dictionary called variety_mappings.

For example, if the rounded-off probability score is 1, then variety_mappings[1] would be Versicolor.

HTML webpage

Having built our Machine Learning model, now let’s build a simple form using HTML to accept the inputs from the user.

Since our objective is not learning how to build an HTML webpage, let’s focus on building the body content. The remaining contents are written to enhance the webpage. Full webpage code can be found here.

We have built our webpage using Bulma CSS. To learn more about it, refer to the documentation for better understanding of the CSS classes.

<body>
    <div id="login-form-container">
        <form action="classify" method="GET">
            <div class="card" style="width: 400px">
            <div class="card-content">
                <div class="media">
                <div class="is-size-4 has-text-centered">Flower Variety Classification</div>
                </div>
                <div class="content">

                <div class="field">
                    <p class="control">
                    Sepal Length: <input class="input" type="number" value='0.00' step='0.01' name="slen" id="slen">
                    </p>
                </div>

                <div class="field">
                    <p class="control">
                    Sepal Width: <input class="input" type="number" value='0.00' step='0.01' name="swid" id="swid">
                    </p>
                </div>

                <div class="field">
                    <p class="control">
                    Petal Length: <input class="input" type="number" value='0.00' step='0.01' name="plen" id="plen">
                    </p>
                </div>

                <div class="field">
                    <p class="control">
                    Petal Width: <input class="input" type="number" value='0.00' step='0.01' name="pwid" id="pwid">
                    </p>
                </div>
                
                <div class="field">
                    <button class="button is-fullwidth is-rounded is-success">Submit</button>
                </div>
                </div>
            </div>
        </form>
    </div>
</body>

The above code is saved as home.html under the directory ./templates/home.html.

To explain the above code in simple words, we created a div tag with class field containing input tags with its respective labels.

Each input tag has fixed styling property like:

  • class = "input"

  • type="number"

  • value='0.00'

  • step='0.01'

  • name and id based on the respective fields

All the div tags are enclosed within a form with action="classify" and method="GET". Here, GET request helps us transport the data from the HTML form to the backend server. To learn more about such methods, this article would help you understand better.

Flask webserver

In Python, we use the Flask framework to host local servers and when routing the webpages. Here, we will use it when deploy our Machine Learning model locally. If you are new to the Flask framework, it is highly recommended to go over this article before building.

To begin, let’s start building by importing the necessary libraries.

import model # Import the python file containing the ML model
from flask import Flask, request, render_template # Import flask libraries

Here, the model refers to the Machine Learning model that we built earlier. To import all the methods from model.py, we specify import model. Apart from our Machine Learning model, we also import other Flask related libraries.

As the first step in building the Flask server we start by initializing the server, and routing it to the default URL path.

# Initialize the flask class and specify the templates directory
app = Flask(__name__,template_folder="templates")

# Default route set as 'home'
@app.route('/home')
def home():
    return render_template('home.html') # Render home.html

In the above snippet, we specified the current module __name__ as an argument to the parameterized constructor Flask(). We also specify the template_folder containing all the webpage related files. Then, we assign the constructor to app.

Now, we set the default route of the server to /home by specifying the path in @app.route() function. This method works whenever the /home route is called for. Here, we set the default page as home.html using the render_template() method.

# Route 'classify' accepts GET request
@app.route('/classify',methods=['GET'])
def classify_type():
    try:
        sepal_len = request.args.get('slen') # Get parameters for sepal length
        sepal_wid = request.args.get('swid') # Get parameters for sepal width
        petal_len = request.args.get('plen') # Get parameters for petal length
        petal_wid = request.args.get('pwid') # Get parameters for petal width

        # Get the output from the classification model
        variety = model.classify(sepal_len, sepal_wid, petal_len, petal_wid)

        # Render the output in new HTML page
        return render_template('output.html', variety=variety)
    except:
        return 'Error'

Similarly, we create a separate route for the Machine Learning model. Here, we use the /classify route with the GET method as the default method.

In this method, we retrieve the data from the form action in home.html through a GET request. Now, we retrieve the data from each of the input fields in the form, using its name attribute. To retrieve, we use request.args.get().

Using the above command, we retrieve the data from all 4 input fields. Later, it is passed to the classify() method of our Machine Learning model model.py.

To call a method in another file, we specify the filename.methodname(). Here, it is model.classify(). This method returns the variety of the flower as a string data type.

To render the returned value i.e the variety of flowers, we specify the output HTML file along with the arguments to be rendered, using the render_template(filename, arguments) command.

Finally, to run the Flask webserver, we must use the app.run() method as shown below:

# Run the Flask server
if(__name__=='__main__'):
    app.run(debug=True)

Output display page

Having predicted the variety of the flower, now we have to display our classification, back in a new HTML webpage.

To do this, we create a very similar HTML webpage like we did earlier. Now, we name a new file as output.html and save it in the directory ./templates/output.html.

<body>
    <div id="login-form-container">
        <div class="card" style="width: 400px">
            <div class="card-content">
                <div class="media">
                    <div class="is-size-4 has-text-centered">
                        {{ variety }}
                    </div>
                </div>
                <form action="home">
                    <div class="field">
                        <button class="button is-fullwidth is-rounded is-success">Retry</button>
                    </div>
                </form>
            </div>
        </div>
    </div>
</body>

In the above code, {{ variety }} specifies the input argument that was passed in render_template() in the Flask server. In Flask, such arguments can be passed along with the respective HTML file, to get rendered in the new HTML file.

Sample outputs

Now, on running the flask server using the command python server.py on your terminal, your development server gets hosted locally. Now, copy and paste the local URL that you get at the start of the server.

To view the landing page, append /home to the existing URL. You can view sample inputs and outputs in the below screenshots.

HTML page to accept details

HTML page to display the variety of flower

From the above images, you can see that Virginica is the classified variety for the given inputs of sepal and petal.

The folder structure should like this:

deploying-machine-learning-model-using-flask
├── iris.csv
├── model.py
├── server.py
├── templates
   ├── home.html
   ├── output.html

Conclusion

In conclusion, we have gone through how Machine Learning models are built, how to connect them with a web application, and how to deploy them locally using Flask. This article serves only as an introduction to deploying Machine Learning models using Flask. It’s highly recommended to try out the code manually by reading further from the referenced articles.

All the codes can be accessed here.

To summarize:

  • We understood how Machine Learning models are deployed.

  • We had an overview of how it can be deployed locally.

  • We also learned about the Flask framework.

Further Reading


Peer Review Contributions by: Lalithnarayan C


About the author

Srishilesh P S

Srishilesh is pursuing his undergraduate studies in Computer Science. He is passionate about Artificial Intelligence and Blockchain. Apart from programming, he also enjoys gaming, reading books, playing football, or practicing karate.

This article was contributed by a student member of Section's Engineering Education Program. Please report any errors or innaccuracies to enged@section.io.