The world’s leading publication for data science, AI, and ML professionals.

End to End Deployment of A Machine Learning Model using Flask

Designing and Building End-to-End Web Applications that leverage Machine Learning using Flask

Leverage Data and Visualization skills - Photo by Arian Darvishi on Unsplash
Leverage Data and Visualization skills – Photo by Arian Darvishi on Unsplash

Machine Learning is pretty – and nifty, if it works right. However, you are limited to showing results to someone who understands the process the way you do. The magic disappears when someone gets to know how it works, and taking others through what it is without visual aid … is about as exciting as watching paint dry.

So, a valid line of thought is to have some visual aid, something easy to use, and something that can show an output which is not limited to a Jupyter Notebook or the Terminal. Here, we introduce Flask: a web application framework that is completely in Python. It boasts minimal setup and fast development times. This means no extra hassle trying to learn a language only for web deployment – plain old Python will do.

Using Flask, we can now bring our machine learning models to life (or at least take them out of notebooks and terminals). Let’s get started!


Sample Problem – Question Classification

Workflow - Photo by Campaign Creators on Unsplash
Workflow – Photo by Campaign Creators on Unsplash

Machine Learning can be used to solve Classification problems and to make a practical model, we look at a simple but effective challenge – Question Classification. The details about the challenge can be found here.

The goal of this problem is to develop a simple Machine Learning model, which can later be deployed using Flask.


Preparing the Dataset

The dataset is pretty much standard, and has 5 columns : Index, Questions, Cat0, Cat1, Cat2.

Cat1 is just the abbreviation of the corresponding data point in Cat0. Cat1 boasts only 6 classes, whereas Cat2 delves deeper and has a finer classification for each Question. We can check for unique values to take care of class imbalance, drop duplicates and remove null values (if any) as part of preparing the dataset. Another interesting point to note is that we cannot use categorical labels directly, so we have to convert each of the Cat1 and Cat2 data points into a class number to be used as target variables in our model.

This can all be done simply as follows:

#read the dataset
df = pd.read_csv('dataset.csv')
#drop duplicates and values, if any
df.drop_duplicates(inplace=True)
df.dropna(inplace=True)
df.reset_index(inplace=True, drop=True)
#convert categorical values into class numbers for our target variables
df['cat_label'] = pd.factorize(df['Category1'])[0]
df['topic_label'] = pd.factorize(df['Category2'])[0]

Deciding on a Feature Extraction method

As mentioned before, text/categorical values cannot be used directly in a Machine Learning model. To use these, we need to convert them into numeric values, or features. Feature Extraction and Feature Engineering in text refer to extracting information from data in a numeric format. To keep things simple, we use use an easy and intuitive method to convert our text into usable features. The TF-IDF is a very intuitive method of modeling text data into usable features :

TF-IDF: Term Frequency x Inverse Document Frequency for all words in the corpus.
TF-IDF: Term Frequency x Inverse Document Frequency for all words in the corpus.

Making a classification model

We have now chosen a method for converting our text into features, and have already formed the target variables as well. All that remains now is to fit a model ….. but, which one? It is important to test out different models before deciding on a final one. Besides, modeling the best classification algorithm is a very simple task via sklearn – and we can see the outputs of different models using a simple fit() and predict().

For this project, we choose SVM, LinearSVM, Decision Trees and Random Forests as our classifiers.

Putting what we have thus far discussed into a simple workflow, we get:

To evaluate which of our models works better, we need to calculate and compare accuracies between classifiers. Since it is a repetitive process, we can make it easier for us by defining a function to evaluate classifiers.

After running the evaluation script, we find that LinearSVC outperforms the rest by a bit. At this point, we can use this as our machine learning model – but we can tune and possibly increase the performance of our model as well. So, the next step is to find the best parameters for our model, using GridSearchCV.

We can follow the same flow for Task 2 as well. Nothing changes, except modeling by remembering class imbalance in our dataset.

Since we have found our best model and possibly tuned it, we want to save it to run future predictions directly without having to train a classifier all over again. Recall that we made use of a vectorizer that fit our data as well. So, it is imperative to store the same vectorizer for our test and prediction data as well.

Remember that we have 6 classes in Cat1, and 40+ in Cat2. A simple way of remembering them is to save a mapping of category_var:class_num in a json/text file. This can be done fairly easily like this:

#dictionaries to map category to label
cat_label_dict, topic_label_dict = {},{}

for val in df['Category1'].unique():
    cat_label_dict[val] = df[df['Category1']==val]['cat_label'].unique()[0]

for val in df['Category2'].unique():
    topic_label_dict[val] = df[df['Category2']==val]['topic_label'].unique()[0]
#print and check the dictionaries
print(cat_label_dict, topic_label_dict)
#save the mappings in text files
with open('category_labels.txt', 'w') as f:
    f.write(str(cat_label_dict))

with open('topic_labels.txt', 'w') as f:
    f.write(str(topic_label_dict))

Making a Prediction Function from saved files

We have successfully finished training, tuning and saving our model! However, our code is a little haywire: it is all over the place and not very well structured. To predict results, we need to have a single function that transforms input sentence to lowercase, extracts features using the saved vectorizer and calls the prediction function using our saved model. To this end, let us make a simple prediction function from our saved files. This piece of modular code will help us when we deploy the application as well.


Making a WebApp to deploy the model

Since our ML model is now ready and can be called using a single function, we are ready to deploy it. For this part, we need to have Flask installed on our local machine.

Flask can simply be installed by running the following in a terminal:

sudo apt-get install python3-flask
pip install flask

For this part, an IDE like VSCode or an editor like Sublime Text is preferred. They help in auto-completion, and give a good idea of our code structure.

Every Flask based web application has 3 distinct things – a ‘templates’ folder (to store html pages), a ‘static’ folder (to store css designs and an optional ‘images’ folder inside : to store images), and a python file to run your app (normally named app.py by convention).

Since many people (like myself) are not very good at designing Web applications, a fast fix is to use already available HTML templates. Choose one that would fit for your use-case, or can be modified to fit one. Here is a starting point for free html template designs.

You can demo the template and try it yourself. You can also make changes in the online editor and see those in the browser directly. It can make for fast web designing if you are uncomfortable using Traditional editors and checking for outputs.

For this project, I chose to have a home page and a prediction page for my web application. Make sure that all html files reside inside the templates folder, and their accompanying css in the static folder.

The main implementation is seen in the prediction page of the application –

Finally, we build our app.py, that runs our back-end: the ML model. To do this, we use the prediction function we wrote earlier and define the routes for each of the html pages. By defining routes, we mean to tell the code what page to render when a particular local html page reference is clicked on.

Also, since we take inputs for our model (usually through an HTML form), we need to set the form action and method accordingly. A very simple way is to use url_for , which sets the route directly to the argument inside the braces. Here, we set it to the predict(), which is the name of the prediction function in app.py.

To access any inputs made using the form at the html page, we use requests.form[”].

Combining all of this into a single app.py file, we write it as follows –

To run our app, we simply type in

python3 app.py

The result should look something like this:

A successfully running Flask Application on port 5000
A successfully running Flask Application on port 5000

This marks the end of deploying our project using Flask.


Why Learn how to make WebApps for Projects?

As a Machine Learning Engineer / Data Scientist or being an enthusiast/practitioner of any of the Data related tracks, it is important to show knowledge of end-to-end development of a product. Flask integrates with pure Python seamlessly, and is hence very easy to develop apps in. Flask should be used in building Proof of Concepts, demonstrating solutions, and for showing development and growth.

Picking up a simple framework like Flask helps to round off the skill-set as a developer as well. Data Science in general is more reliant on how effectively you can demonstrate and show your ideas to a group of individuals that may not particularly be tech or data aligned.

Data Scientists are, at the core, still software engineers. As such, building, testing, developing and deploying applications should be a part of every Software Engineer’s skill-set.

If you enjoyed the read, drop a comment and show your appreciation by clapping! You can also connect with me directly using my linkedin profile.

The entire code for this project can be found at my github repository.


Related Articles