Deploying a Machine Learning Model as a REST API

Artwork by Igor Kozak

About the Model

Distribution of ratings from the Kaggle dataset

REST API Guide

Import Libraries and Load Pickles

from flask import Flask
from flask_restful import reqparse, abort, Api, Resource
import pickle
import numpy as np
from model import NLPModel
app = Flask(__name__)
api = Api(app)
# create new model object
model = NLPModel()
# load trained classifier
clf_path = 'lib/models/SentimentClassifier.pkl'
with open(clf_path, 'rb') as f:
model.clf = pickle.load(f)
# load trained vectorizer
vec_path = 'lib/models/TFIDFVectorizer.pkl'
with open(vec_path, 'rb') as f:
model.vectorizer = pickle.load(f)

Create an argument parser

# argument parsing
parser = reqparse.RequestParser()
parser.add_argument('query')

Resource Class Object

class PredictSentiment(Resource):
def get(self):
# use parser and find the user's query
args = parser.parse_args()
user_query = args['query']
# vectorize the user's query and make a prediction
uq_vectorized = model.vectorizer_transform(
np.array([user_query]))
prediction = model.predict(uq_vectorized)
pred_proba = model.predict_proba(uq_vectorized)
# Output 'Negative' or 'Positive' along with the score
if prediction == 0:
pred_text = 'Negative'
else:
pred_text = 'Positive'

# round the predict proba value and set to new variable
confidence = round(pred_proba[0], 3)
# create JSON object
output = {'prediction': pred_text, 'confidence': confidence}

return output

Endpoints

api.add_resource(PredictSentiment, '/')

# example of another endpoint
api.add_resource(PredictRatings, '/ratings')

Name == Main Block

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

User Requests

url = 'http://127.0.0.1:5000/'
params ={'query': 'that movie was boring'}
response = requests.get(url, params)
response.json()
Output: {'confidence': 0.128, 'prediction': 'Negative'}
$ curl -X GET http://127.0.0.1:5000/ -d query='that movie was boring'
{
"prediction": "Negative",
"confidence": 0.128
}
$ http http://127.0.0.1:5000/ query=='that movie was boring'HTTP/1.0 200 OK
Content-Length: 58
Content-Type: application/json
Date: Fri, 31 Aug 2018 18:49:25 GMT
Server: Werkzeug/0.14.1 Python/3.6.3
{
"confidence": 0.128,
"prediction": "Negative"
}

Full app.py code

File Structure

sentiment-clf/
├── README.md
├── app.py # Flask REST API script
├── build_model.py # script to build and pickle the classifier
├── model.py # script for the classifier class object
├── util.py # helper functions
├── requirements.txt
└── lib/
├── data/ # data from Kaggle
│ ├── sampleSubmission.csv
│ ├── test.tsv
│ └── train.tsv
└── models/ # pickled models for import into API script
├── SentimentClassifier.pkl
└── TFIDFVectorizer.pkl

Deployment

Closing