In the last two weeks, we have shown you how to create your own Flask application and how to build a sentiment classifier from tweets using the Twitter API and nltk. Today we will combine these two things to make them work together.

STORING THE MODEL

First, we need to store our classifier from last week, so we can use it in our application. For this, we will use the package Pickle. Insert the following code from part II of the tutorial into the file and save the model to your hard drive.

import pickle
path = "where-you-want-to-save-your-model"
pickle.dump( classifier, open(path + "sentiment_classifier.p", "wb" ) )

The classifier is the instance of the Naive Bayes classifier from part II of the tutorial.

Now we can adjust the code of our Flask application so we load our model right after the launch.

from flask import Flask
from flask_restful import Resource, Api
import pickle

app = Flask(__name__, static_url_path='')
api = Api(app)

path = "path-to-the-model"
classifier = pickle.load(open(path + "sentiment_classifier.p", "rb" ) )

@app.route("/index.html", methods=['POST', 'GET'])
def hello_world():
    return render_template("index.html")
if __name__ == '__main__':
    app.run(host='0.0.0.0', port='5000')

Now when we launch our application, the model will be loaded into the memory during the startup.
 

ADJUSTING HTML FILES

As the next step, we have to adjust our HTML files. First, we will focus on index.html. The form that will send the HTTP request to our API needs to be added. If you already have some experience with HTML this will be very easy for you. If you are not sure about this you can use our suggestion below:

<BODY>
    <p> Sentiment Analysis API </p>
    <form id = "text_sentiment" name = "shift" action="/sentiment_analysis" method = "POST">
          <p>
          <b>Write in your text into field below</b><br>
          <input type="text" name="input_text" value = "" ><br>
          <p>
          <input type="submit", value="Get Sentiment">
          </p>
    </form>
</BODY>

Our form consists of 2 inputs: first, we have the text field where we will write the text we want to analyze and the submit button. Once the form is submitted it will send the POST request "/sentiment_analysis" to our API. If you want to read more about HTTP requests you can visit this page.

We have created two HTML files in the first part of this tutorial. We have used index.html but we haven't done anything with results.html so far. In this file, we need to make sure that Python variables passed back from our API will be shown in the browser. 

<!DOCTYPE html>
<html lang="en">
<HEAD>
    <TITLE>
        Sentiment of inputted text
    </TITLE>
</HEAD>
<BODY>
    <p> <b> Your text: </b>  {{full_text}} </p>
    <p> <b> Sentiment: </b>   {{sentiment}} </p>
    <a href="/index.html"> return to the index.html</a>
 </BODY>
</html>

In the code above you can see the variable names in {{ }}. These are used to show the value of variables which were sent from the Flask application.
 

FINALIZING THE API

In the last part of this short tutorial series we will make our Flask application process the input from the form in index.html, score the text with our model from last week and output the sentiment back into the browser.

We will add two functions into our main file my_first_api.py:

# function for word features from part II of the tutorial
def word_feats(words):
    return dict([(word, True) for word in words])

and

# function is run when /sentiment_analysis POST request is sent from the form in HTML file
@app.route("/sentiment_analysis", methods=['POST'])
def get_sentiment():
    # we make sure that request method is POST
    if request.method == 'POST':
        # we assigned the input from form into the Python variable
        result = request.form
    # if result doesn't exist then abort
    if not result:
        abort(400)
    # classify the text which was submitted in the form. 
    # function word_feats from last week is called
    res = classifier.classify(word_feats(result["input_text"].split()))
    # return the file results.html and send also two Python variables 
    # name of the variables have to be same as in {{}} in results.html
    return render_template("results.html", full_text = result["input_text"],
                           sentiment = res)


The code is commented so you can understand each step. If you run print result after it is loaded in the beginning of the function you will get
 

ImmutableMultiDict([('input_text', u'your text')])

 

This values inside this variable type can be accessed the same way as in normal Python dictionary.

For your get_sentiment() function to work properly, you need to import the method request directly from Flask.
 

from flask import request

Now we can launch the API from the terminal and test it with a couple of examples.

Text: "best day of my life" returns "pos".

Text: "my dog died" returns "neg".

In the end, you should have three files in the directory of your project: my_first_api.py in the main directory and index.html and results.html in the subdirectory templates. You can see the complete code without comments for all the files below.

my_first_api.py:

from flask import Flask, request
from flask import render_template
from flask_restful import Resource, Api
import pickle

app = Flask(__name__)
api = Api(app)

path = ""
classifier = pickle.load(open(path + "sentiment_classifier.p", "rb" ) )

def word_feats(words):
    return dict([(word, True) for word in words])
    
@app.route("/index.html", methods=['POST', 'GET'])
def hello_world():
    return render_template("index.html")

@app.route("/sentiment_analysis", methods=['POST'])
def get_sentiment():
    if request.method == 'POST':
        result = request.form
    if not result:
        abort(400)
    res = classifier.classify(word_feats(result["input_text"].split()))
    return render_template("results.html", full_text = result["input_text"],
                           sentiment = res)

if __name__ == '__main__':
    app.run(host='0.0.0.0', port='5000')

index.html:

<!DOCTYPE html>
<html lang="en">
<HEAD>
        <TITLE>
            My First API
        </TITLE>
</HEAD>
<BODY>
    <p> Sentiment Analysis API </p>
    <form id = "text_sentiment" name = "text_sentiment" action="/sentiment_analysis" method = "POST">
          <p>
          <b>Write in your text into field below</b><br>
          <input type="text" name="input_text" value = "" ><br>
          <p>
          <input type="submit", value="Get sentiment">
          </p>
    </form>
</BODY>
</html>

results.html:

<!DOCTYPE html>
<html lang="en">
<HEAD>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <TITLE>
            Sentiment of inputted text
        </TITLE>    
</HEAD>
<BODY>
    <p> <b> Your text: </b>  {{full_text}} </p>
    <p> <b> Sentiment: </b>   {{sentiment}} </p>
    <a href="/index.html"> return to the index.html</a>
</BODY>
</html>


CONCLUSION

In last three weeks, we have been working on our own API. You can now run it and explore the assigned sentiments for specific sentences. Let us know if you have the expected results. You can also check our online Bootcamp for more Data Science education.  

 

Comment