Deploying ML model to flask with joblib
In this blog, we will know how to deploy a Machine Learning model on a Flask App. In this blog, I am going to deploy a Simple Spam Classification Model to flask App.
If you have read before about deployment of the ML model you have heard of Pickle. This is most famous library for model deployment. But the question is, Is it most suitable in every case. The answer is no.
When we made a model with the sckit-learn classifiers, then Pickle faces some issues. These issues are also described in docs. But the Solution is the JOBLIB library. In this blog We will create a flask app and deploy the model in flask App with help of joblib.
from here you can download pre-trained model used in this blog. Models are in output file on kaggle- https://www.kaggle.com/thedeathcure/sms-spam-filtering. Model files are present in both format - model.joblib(joblib) and model.pkl (pickle)
Create app.py
https://gist.github.com/maze-runnar/4b455b2b2bdb0ba45c744da55dce5160
import requests
from flask import Flask, request,render_template
import sys
app = Flask(__name__)
app.config['DEBUG'] = True
// Your view goes here
if __name__ == "__main__":
app.run(debug = True)
create your view
here I am using my pre-trained model so all libraries that are going to use in prediction with your model you have to import that.
from sklearn import svm
from joblib import dump, load
## loading the model
clf = load('/home/saurabh/Desktop/smsspamcollection/frontend/model1.joblib')
@app.route('/', methods = ["GET","POST"])
def index():
if(request.method == "POST"):
#city = request.form['city']
text_msg = request.form['sms']
my_msg = find_features(text_msg)
prediction = clf.classify_many(my_msg) ## make your prediction here
x = ""
if(prediction[0] == 0):
x = "Not a spam, it's ok "
else:
x = "it's a spam"
return render_template('mainpage.html',prediction = x)
else:
return render_template('mainpage.html')
In your templates the mainpage.html would be like -
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="//maxcdn.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css" rel="stylesheet" id="bootstrap-css">
<script src="//maxcdn.bootstrapcdn.com/bootstrap/4.1.1/js/bootstrap.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<!------ Include the above in your HEAD tag ---------->
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.1.0/css/all.css" integrity="sha384-lKuwvrZot6UHsBSfcMvOkWwlCMgc0TaWr+30HWe3a4ltaBwTZhyTEggF5tJv8tbt" crossorigin="anonymous">
<div class="container">
<style>
/* Style the body */
body {
font-family: Arial;
margin: 0;
}
/* Header/Logo Title */
.header {
padding: 60px;
text-align: center;
background: orange;
color: white;
font-size: 30px;
}
/* Page Content */
.content {padding:20px;}
</style>
</head>
<body>
<div class="header">
<h1>Spam Detector</h1>
<p style="font-family: cursive;">98.79% Accuracy NaiveBayes Classifier</p>
</div>
<br/>
<style>
input[type=text], select {
width: 100%;
padding: 12px 20px;
margin: 8px 0;
display: inline-block;
border: 1px solid #ccc;
border-radius: 4px;
box-sizing: border-box;
}
input[type=submit] {
width: 30%;
justify-content: center;
background-color: orange;
color: white;
padding: 10px 20px;
margin: 8px 0;
border: none;
border-radius: 15px 0 15px 0;
cursor: pointer;
}
input[type=submit]:hover {
background-color: #45a049;
}
div {
border-radius: 5px;
background-color: lightgrey;
padding: 20px;
}
</style>
<div>
<form action="/" method = "post">
<label for="fname" style="font-family: cursive;">Message</label>
<input type="text" name = "sms" id="fname" name="firstname" placeholder="type message here ..">
<br><br>
<div style="text-align:center;">
<input type="submit" value="classify">
</div>
</form>
</div>
</body>
<!-------let's go and get that son of a b****----->
<div>
<span style="color:red; font-family: cursive;font-size: 20px"><i>{{prediction}}</i></span>
</div>
Some Common Errors during Deployment
Errors are inevitable when you try to go out of the box or try something new in development.
The very common error is -ModuleNotFoundError: No module named 'sklearn.svm._classes'
The reason for this error is the version difference of sckit-learn. This occurs due to when you use pre-trained model or you trained a model on kaggle or colab and try to delay it on your local. Then you have to install same version of sckit-learn on your local too.
pip install -U sckit-learn==0.22.1
mine model used this version. I tried this and error resolved. So keep the versions in mind.
Once again just for revision -
## loading the model
clf = load('/home/saurabh/Desktop/smsspamcollection/frontend/model1.joblib')
prediction = clf.classify_many(my_msg) ## make your prediction here
Complete app.py to use with my model -
import requests from flask import Flask, request,render_template import sys import nltk import sklearn import pandas import numpy import pandas as pd import numpy as np from sklearn.preprocessing import LabelEncoder #import pickle ##load pre-trained model using pickle.. from nltk.tokenize import word_tokenize from sklearn import model_selection from nltk.classify.scikitlearn import SklearnClassifier#SVM classsifier (support vector machine) from sklearn.svm import SVC from sklearn.metrics import classification_report, accuracy_score, confusion_matrix app = Flask(__name__) app.config['DEBUG'] = True df = pd.read_table('/home/saurabh/Desktop/smsspamcollection/SMSSpamCollection', header=None, encoding='utf-8') classes = df[0] #from sklearn.preprocessing import LabelEncoder # so convert spam to 1 and ham tabso 0 encoder = LabelEncoder() y = encoder.fit_transform(classes) text_messages = df[1] processed = text_messages.str.replace(r'^.+@[^\.].*\.[a-z]{2,}$', 'emailaddress') # Replace URLs with 'webaddress' # you can use any regex expression they are basically taken from the wikipedia processed = processed.str.replace(r'^http\://[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}(/\S*)?$', 'webaddress') # Replace money symbols with 'moneysymb' (£ can by typed with ALT key + 156) # you can use any regex expression they are basically taken from the wikipedia processed = processed.str.replace(r'£|\$', 'moneysymb') # Replace 10 digit phone numbers (formats include paranthesis, spaces, no spaces, dashes) with 'phonenumber' # you can use any regex expression they are basically taken from the wikipedia processed = processed.str.replace(r'^\(?[\d]{3}\)?[\s-]?[\d]{3}[\s-]?[\d]{4}$', 'phonenumbr') # Replace numbers with 'numbr' # you can use any regex expression they are basically taken from the wikipedia processed = processed.str.replace(r'\d+(\.\d+)?', 'numbr') # Remove punctuation # you can use any regex expression they are basically taken from the wikipedia processed = processed.str.replace(r'[^\w\d\s]', ' ') # Replace whitespace between terms with a single space processed = processed.str.replace(r'\s+', ' ') # Remove leading and trailing whitespace processed = processed.str.replace(r'^\s+|\s+?$', '') processed = processed.str.lower() from nltk.corpus import stopwords s = stopwords.words('english') processed = processed.apply(lambda x: ' '.join(term for term in x.split() if term not in s)) ps = nltk.PorterStemmer() # it removes the synonyms and similar sounding words.. processed = processed.apply(lambda x: ' '.join(ps.stem(term) for term in x.split())) all_words = [] for message in processed: words = word_tokenize(message) for w in words: all_words.append(w) all_words = nltk.FreqDist(all_words) word_features = list(all_words.keys()) def find_features(message): words = word_tokenize(message) features = {} for word in word_features: features[word] = (word in words) return features from sklearn import svm from joblib import dump, load clf = load('/home/saurabh/Desktop/smsspamcollection/frontend/model1.joblib') @app.route('/', methods = ["GET","POST"]) def index(): if(request.method == "POST"): #city = request.form['city'] text_msg = request.form['sms'] my_msg = find_features(text_msg) prediction = clf.classify_many(my_msg) x = "" if(prediction[0] == 0): x = "Not a spam, it's ok " else: x = "it's a spam" return render_template('mainpage.html',prediction = x) else: return render_template('mainpage.html') @app.route('/aboutme') def about(): return render_template('aboutme.html') if __name__ == "__main__": app.run(debug = True)
Comments
AWS Training In Chennai
AWS Online Training
AWS Training in Bangalore