Deploy Machine Learning Model using Flask to Heroku — Beginners(Part 2)

Joan Ngugi
Analytics Vidhya
Published in
7 min readFeb 9, 2021

--

This is the second part of the tutorial on how to create and deploy a machine learning model on Heroku using Flask. The first part was about data pre-processing and creation of a logistic regression model using JupyterNotebook.

Part 2 will be a guide on how to structure your flask application and embed your machine learning model in it, as well as uploading the application on GitHub.

Structuring the Flask Application

I am using PyCharm as my IDE. Make sure you have installed the packages we used in our model, as well as flask, numpy and Gunicorn. Gunicorn will allow us to serve and run our flask application on Heroku.

  • Flask
  • Pandas
  • Numpy
  • Scikit-learn
  • Gunicorn
  • Pickle

The high level structure of our flask app has the following files: The model.py contains our machine learning model. Our app.py contains our logic and it’s where we import our pickle model and flask modules. The model.pkl file packages our machine learning model. Our index.html outputs our web page, the Procfile allows us to deploy our app to Heroku and our requirements.txt contains all our imported libraries.

Let us now break down the structuring into steps:

Step 1: Model.py

We are using the model from the JupyterNotebook we had previously created. Only that this time we don’t need to include the data exploration and machine learning model validation steps. We remove those sections since we’ve already tested our model and therefore we just need to import our dataset, specify our X and y features and split our training and testing set and fit them in our logistic model.

The additional line I have here is pickle.dump(logreg, open(‘model.pkl’,’wb’)). We are essentially saving our trained model(logreg) to the disk using our pickle library. When you run python model.py your model.pkl file is saved.

import pandas as pd

df=pd.read_csv('diabetes.csv')


## Import ML libraries
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression

import pickle


# Define our X and y features and split into training/test sets
X = df.drop(['Outcome'], axis=1)
y = df['Outcome']

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=109)


X_train.head()


logreg = LogisticRegression(max_iter=1000)
logreg.fit(X_train,y_train)

print(logreg.predict([[1,103,30,38,83,43.3,0.183,33]]))


# Saving model to disk
# Pickle serializes objects so they can be saved to a file, and loaded in a program again later on.
pickle.dump(logreg, open('model.pkl','wb'))

Make sure to run the below command to output your pickle file

python model.py

Step 2: app.py

import numpy as np
from flask import Flask, request, render_template
import pickle

app = Flask(__name__)
# read our pickle file and label our logisticmodel as model
model = pickle.load(open('model.pkl', 'rb'))

@app.route('/')
def home():
return render_template('index.html')

@app.route('/predict',methods=['POST','GET'])
def predict():

int_features = [float(x) for x in request.form.values()]
final_features = [np.array(int_features)]
prediction = model.predict(final_features)


if prediction==0:
return render_template('index.html',
prediction_text='Low chances of patient having diabetes'.format(prediction),
)
else:
return render_template('index.html',
prediction_text='High chances of patient having diabetes'.format(prediction),
)



if __name__ == "__main__":
app.run(debug=True)

In this file we have two methods: home() and predict(). The home method renders our index.html page and gives us the home page interface below.

The predict method is called when your click the Predict button above in order to get your prediction result and you get the interface with your results as below

We have also imported our model from the pickle file, and then in the predict method we are taking the values entered by the user in the form that is in the index.html file and then proceed to predict those values using the model from the pickle file. The values entered by the use are essentially the X features from our machine learning model in model.py.

A key thing to note is that for better user experience I have replaced outcome 0 and 1 with a string text, so that if outcome is equal to 0, it reads Low chances of patient having diabetes and if outcome is equal to 1 it reads High chances of patient having diabetes.

Step 3: Index.html

Our index.html is a simple one. It contains a form where we will enter our X features: Glucose,BMI etc. You will get an error if your form features are not equal to the number of the X features in your model. The line {{ prediction_text }} is where our final output shall be. In app.py {{ prediction_text }} was equated to our Outcome feature.

<!DOCTYPE html>
<html >

<head>
<meta charset="UTF-8">
<title>COVID-19 Predictor</title>
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">

<!-- jQuery library -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>

<!-- Popper JS -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.min.js"></script>

<!-- Latest compiled JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>

</head>

<body>
<nav class="navbar navbar-expand-sm bg-primary navbar-light">
<ul class="navbar-nav">
<li class="nav-item active">
<a class="nav-link" href="index.html">Diabetes Predictor</a>
</li>

</ul>
</nav>


<br>
<br>

<form action="{{ url_for('predict')}}"method="post">
<input type="text" name='Pregnancies' placeholder="Pregnancies" required="required" />
<input type="text" name="Glucose" placeholder="Glucose" required="required" />
<input type="text" name="BloodPressure" placeholder="BloodPressure" required="required" />
<input type="text" name="SkinThickness" placeholder="kinThickness" required="required" />
<input type="text" name="Insulin" placeholder="Insulin" required="required" />
<input type="text" name="BMI" placeholder="BMI" required="required" />

<input type="text" name="DiabetesPedigreeFunction" placeholder="DiabetesPedigreeFunction" required="required" />
<input type="text" name="Age" placeholder="Age" required="required" />
<br>
<br>
<button type="submit" class="btn btn-success btn-block btn-large">Predict</button>

</form>
<br>
<br>
{{ prediction_text }}

</div>

</body>
</html>

Step 4: Procfile

Our Procfile is a one liner file that contains the instruction below:

web: gunicorn app:app

This is a must have file when you want to deploy your web applications. It should be named exactly Procfile, something like Procfile.txt will not work!It is a file that describes how you want to run your web application. Every language and framework contains a standard way of writing that file. The part on the left is the process type; the part on the right is the command to run to start that process.

Step 5: requirements.txt

In your terminal run the command below:

pip freeze > requirements.txt

This is the command that gives us our requirements.txt file. This is a very important file that not only guides other developers on the version of the python packages you have used in your app , but it is also a file that Heroku uses to run your app during deployment. Your requirements file should look something like the image below. A list of your packages and the version. Heroku might bring an error with versions during deployment and you can always downgrade your package versions.

You can test and run you application by running the following command in your terminal

python app.py

You have succeeded if you get the following response in your terminal

Click on the link provided and you should have your app running in your local machine

The final part will now involve pushing your code to GitHub. Since this is not a GitHub tutorial and this could also be new to you, the simplest way to have your code in GitHub is just by uploading the files like you would upload any other file on the web.

On your GitHub repositories section, select new to create your new repository (folder that will contain your code).

Give your repo a name, you can tick the README file as well and click on Create repository.

From the new created repo, click on Add Files> Upload Files. You then proceed to add your flask application files by simply dragging them on the interface. Click on Commit changes to upload your files.

Your final output should have the following files. The Diabeteslog file is not part of it. This is the notebook file that we used in part 1 to create and evaluate our model.

Great! This is the second part of our tutorial. The final part, part 3, is the easiest and it is a tutorial on how to deploy our app from GitHub to Heroku.

--

--

Joan Ngugi
Analytics Vidhya

Big Data & Analytics, Data Science, Machine Learning, Data Engineering | ngugijoan.com

Recommended from Medium

Lists

See more recommendations