Build & Deploy a Spam Classifier app on Heroku Cloud in 10 minutes!

Spam or not spam?

Building a Spam Message Classifier and making an application of it deployed on Heroku

Today we will be building a neat bare bones Spam Message Classifier, a Natural Language Processing based model. Then we will build a flask application which will render an HTML based home page and a prediction page. The user will input text in the home page and the application will predict whether it seems like a Spam message or a Ham (not spam) on the prediction page. This flask API will be deployed in public host on Heroku. Heroku is the obvious choice here as it’s super quick and super easy. And did I mention it is free? Yes it is! Check out and play with the app yourself first by clicking on the button below to know what you’ll be building.

So now that you’ve seen it, let’s dive right in!


The Model

The first step will be to build our NLP model that takes in natural text from user and predicts whether it is a Spam or Ham(not a spam). We will do this in a few pieces of python code. The complete code and the dataset is available on my Github. First, let’s import all the libraries required.

import pandas as pd  #Pandas for data pre-processing

import pickle #Pickle for pickling (saving) the model 

from sklearn.feature_extraction.text import CountVectorizer #To Vectorize the textual data 

from sklearn.naive_bayes import MultinomialNB #The algorithm for prediction 

from sklearn.externals import joblib #Alternative Usage of Saved Model 

from sklearn.model_selection import train_test_split #Validation split 

Next, we need to load the data and split into text data (X) and labels (y).

df = pd.read_csv("spam.csv", encoding="latin-1")

df.drop(['Unnamed: 2', 'Unnamed: 3', 'Unnamed: 4'], axis=1, inplace=True) #Some garbage features that need to be removed

# Text and Labels

df['label'] = df['class'].map({'ham': 0, 'spam': 1}) 

X = df['message']

y = df['label'] 

Now we need to vectorize (convert text to numerical form) the textual data by using Count Vectorizer. Then just split the training and testing data. No further text preprocessing is taken into consideration as our aim is to build a model quickly and deploy it. You can experiment with the text cleaning part for yourself to make the performance better.

# Extract Feature With CountVectorizer 

cv = CountVectorizer() 

X = cv.fit_transform(X) # Fit the Data 

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=42) 

Once this is done, we just need to fit the model and save it as a pickle file which will later be loaded in the flask app.

#Naive Bayes Classifier  

clf = MultinomialNB() 
clf.fit(X_train,y_train) 
print(clf.score(X_test,y_test)) 

#Alternative Usage of Saved Model 

joblib.dump(clf, 'NB_spam_model.pkl') 
joblib.dump(cv, 'cv.pkl') 

Notice here that we have saved the Naive Bayes’ model and the count vectorizer as well. This is because for your the text input which will be taken from user, will have to be vectorized using the same Count Vectorizer parameters as the model was trained on. Okay, so now we have our model and the vectorizer as well. 

Next we need to build the flask app which will connect the NLP model we just built to our browser and later host it on cloud.


The Flask App

The flask application will route the user to the home page as soon as user accesses the URL of the application. Later when user inputs the text and hits the predict button, it will redirect it to the prediction page and render the output. Let’s see how it’s done.

We need to import flask and a few other functions. You would need to install flask by a simple pip install command if you don’t already have it.

from flask import Flask, render_template, request 

Here, Flask will be used to define the app which we are using. Then render_template will render the home page (home.html) and the prediction page (result.html). And the request will be used to retrieve the text input which will be sent to the flask app via the HTML Post method from the HTML page.

Now we need to define the flask app and its default routing to the home page, which is home.html. We will define a function will do nothing but render the home page when the application URL is called.

app = Flask(__name__) 

@app.route('/') #Routes the app to below task when the URL is called 

def home(): 

    return render_template('home.html') 

Now comes the main part of the app, the prediction. We need to define a function that opens and loads the NLP model and Count Vectorizer pickle files. It then retrieves the text input which is sent to it via the POST method. The retrieved text input is then vectorized using the same vectorizer and dumped to our model to get the prediction. That’s it! We now just need to render this prediction result back on the prediction page and we’re done.

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

def predict_fun(): 

    NB_spam_model = open('NB_spam_model.pkl','rb') 
    clf = joblib.load(NB_spam_model)
	
    cv_model = open('cv.pkl', 'rb')
    cv = joblib.load(cv_model)	
	
    if request.method == 'POST': 

        message = request.form['message'] 
        data = [message] 
        vect = cv.transform(data).toarray()
        my_prediction = clf.predict(vect) 

    return render_template('result.html',prediction = my_prediction)   

#Calling the main function and running the flask app 

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

Our model and flask apps are done. We now just need to deploy these files on Heroku. 


Deployment

To deploy the application on Heroku you need to push all the files on your Github which will be linked to Heroku. You will need to upload following files to your repository :

  1. NLP model pickle
  2. Count Vectorizer pickle
  3. Flask app
  4. HTML & CSS files 
  5. Requirements file
  6. Procfile

Okay so you might be wondering what requirements and the procfile files are. The requirements is a text file which contains all the dependencies (libraries like pandas, flask etc.) and their versions required for the app to run as expected. Heroku will install all these dependencies prior to deploying the app. Procfile is a configuration file which looks something like:

web: gunicorn app1:app

Here ‘app1’ is my flask file name which is ‘app1.py’ and ‘app’ is the flask app we defined earlier in the code above. This just tells Heroku to look for the flask file named app1 and in it the flask app defined as ‘app’.

Once you’re done pushing all the files to a new github repository, you will need to create an app on Heroku and connect your github repository to it. To do this, just go to Heroku. Create an account if you haven’t already and go to ‘create new app’.

Create new app

In the newly created app, you need to connect to the github repository which has the code. Search for the github repository name in the search box and hit the ‘Connect’ button.

Connect Github repository to Heroku
Github connected

Once connected you just need to hit the ‘Deploy’ button and you’re done! Heroku will first check for the requirements file and install all the dependencies and then deploy the flask app to public host. A URL will be generated which is the URL of your application. Just copy it and open it in your browser and voila! you’re done.

Hit Deploy !

That was it for this tutorial. Hope you got the app running and got decent results! 

If you got this far and have the app ready, give yourself a pat on the back. You deserve it!

So we used Heroku Cloud here as it’s so quick and easy to setup. However I encourage you to try deploying the app on other cloud platforms as well – like AWS EC2, Google Cloud Platform and Azure.

Feel free to get the source code from my github and reach out to me for any queries and suggestions on LinkedIn.

See you on the next post, Cheers! 

Image Credits
Featured Image: Unsplash
In-Post Photos: Photos taken by author, June 2020

About The Author

Scroll to Top
Share via
Copy link
Powered by Social Snap