Building and Deploying a Spam Detection Model: Section 2

This is a continuation of our guest post from the brilliant Ehi. In this section, we shall continue on how to setup our model on Flask and deploying to Heroku.  

Setting up the development environment: We’ll start by creating a virtual environment to manage all the packages needed for this application by following these steps below:

  • Create a new folder (anywhere) and cd into it. Mine is called spam_detectionon my desktop.
  • Initiate a virtual environment in your folder using: virtualenv .env

Note: Virtual environment has to be already installed on your computer for that command to work. Otherwise, install it from command prompt using: pip install virtualenv

  • Activate the .env file using: source .env/bin/activate
  • Initialize git using: git init
  • Then install the necessary packages:  pip install flask gunicorn nltk pandas sklearn numpy pickle 
  • Finally, create a requirements.txt file using: pip freeze > requirements.txt

Note: The requirements.txtfile is what Heroku needs to install those packages on the server in order for the application to run:


Setting up our Flask Project

  • Copy the spam.csv you downloaded from kaggle file into your project folder.

  • Create an file that will handle all the logic for this application.
  • Create a new folder inside our working folder called templates, inside it, create a html file called index.html. This file will have a textarea where people can enter sample message to test our model. Now our working directory will look like this:

Screenshot from 2019-02-16 13-54-09

The file contains the main code that will be executed by the Python interpreter to run the Flask web application, it includes the code for classifying messages:

from flask import Flask,render_template,url_for,request
import pandas as pd
import pickle
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.naive_bayes import MultinomialNB
from sklearn.externals import joblib

app = Flask(__name__)
@app.route('/', methods=['POST','GET'])

def predict():
   if request.method == 'GET':
   return render_template('index.html')
   df= pd.read_csv("spam.csv", encoding="latin-1")
   df.drop(['Unnamed: 2', 'Unnamed: 3', 'Unnamed: 4'], axis=1, inplace=True)

   # Features and Labels
   df['label'] = df['v1'].map({'ham': 0, 'spam': 1})
   df['message'] = df['v2']

   X = df['message']
   y = df['label']

   # Feature Extraction and Bow creation using CountVectorizer
   bow_transformer = CountVectorizer()
   X = bow_transformer.fit_transform(df['message'])

   #Load the model that was created initially
   spam_model = open('our_model.pkl','rb')
   clf = joblib.load(spam_model)

   if request.method == 'POST':
      message = request.form['sample_text']
      data = [message]
      vect = bow_transformer.transform(data).toarray()
      my_prediction = clf.predict(vect)

      my_prediction = str(my_prediction[0])
      if my_prediction == '1':
         return "That looks like a spam message"
         return "This looks like a ham message."

if __name__ == '__predict__':


At the top of that file, we import all packages needed in our application. Next we declared the argument __name__ to refer to the name of our app’s module which tells Flask where to look for the html (templates) file.

In the line @app.route('/', methods=['POST','GET'] we used the route('/' decorator to tell Flask which URL should trigger our predict function along with their appropriate actions (methods=['POST','GET'])

Notice our function def predict() has two methods: ‘GET’ which displays the index.html page where we will enter a sample message and the POST’ method which runs the sample message through our model. We use the joblib.load(to load the saved model so as to classify that sample message as either spam or ham.  Lastly, the line __name__ == '__main__'runs the application on the server anytime this script is executed by the Python interpreter.


The index.htmfile is what renders the textarea where we will enter a sample message:

<!DOCTYPE html>
  <!-- Latest compiled and minified CSS -->
  <link rel="stylesheet" href="" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">

  <!-- Optional theme -->
  <link rel="stylesheet" href="" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">

  <!-- Latest compiled and minified JavaScript -->
  <script src="" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>

   <title>Spam Detection App</title>


  <div class="container">
   <div class="jumbotron">
    <h2>Spam Detection App</h2>
    <p>Enter a text message and I'll tell you whether it's spam or not.</p>

   <form method="post" action="{{ url_for('predict') }}">

   <div class="form-group">
     <label for="Review">Message</label>
     <textarea name="sample_text" class="form-control" placeholder="Enter Sample Message"></textarea>


    <button type="submit" class="btn btn-primary">Predict</button>


The form action url_forpasses the content of the message box to the predict()method in our app.pyto process the form.

Before we run our application, we need to export the FLASK_APP environment variable then turn the debug mode on so that we don’t have to restart our server every time we make changes to our file. To do this, locate the  activatefile in the directory .env/bin/activateand paste the following lines there:

export FLASK_DEBUG=true

Now run the app from your command line using flask runand type in your browser to see your application:

unnamed (1)

Hosting the Project on Heroku

Before we can host our application, we need to first install Gunicorn web server, which is a pure-Python HTTP server for WSGI applications. It allows you to run any Python application concurrently by running multiple Python processes within a single dyno. Follow the steps below to set that up:

  • From command line, install it using: pip install gunicorn
  • When the installation is complete, create a file in your working directory and name it Procfile (do not give it any extension please).

The Procfile is where we declare the command that is run by your application’s dynos on the Heroku platform.

  • Now open the Procfile and paste this line inside it: web: gunicorn app:app

Setting up Heroku

  • Go ahead and create an account on heroku if you don’t have one yet.
  • Then install the Heroku CLI, which enables us to deploy our application. When that is done, type heroku loginstill in your working directory, you will be prompted to enter your email address and password.
  • From command line, create an app on Heroku and give it your preferred name: heroku create myappname
  • Set our git repository link to the one provided by Heroku using: git remote add origin{myappname}.git
  • Confirm that the remote origin has been added using: git remote -v

In your Heroku dashboard on your browser, locate and open the newly created app then click on settings.  Scroll down the page, and click the Add Buildpack button you’ll see a page like below, select python and save. We did that to inform Heroku what language our application is built in.


Deploying the App

We’re almost done! We need to run our regular git commands to deploy app to heroku:

git add .
git commit -m “Your commit message”
git push heroku master

Now, let’s head over to our Heroku app link (here) to test our application.


You got to this point, great job! Now we have our Spam detection app which can be used by anyone. Feel free to extend this app by training it with more data or experimenting with different algorithms or even improving your accuracy. Now you have the foundation, go do more! Head over to my github repository to find the complete code used in this article.   

We hope you’ve learnt a lot via this tutorial, join our mission to promote more women of color in tech tutorials. Share this link and refer any awesome woman that should be featured at our Guest lounge via

You may also like

Leave a Reply

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