diff --git a/Sentiment Classifier API/app.py b/Sentiment Classifier API/app.py new file mode 100644 index 0000000..42381ac --- /dev/null +++ b/Sentiment Classifier API/app.py @@ -0,0 +1,51 @@ +from flask import Flask +from flask_restful import reqparse, abort, Api, Resource +import pickle +import numpy as np +from model import SentimentClassifierModel + +app = Flask(__name__) +api = Api(app) + +model = SentimentClassifierModel() + +classifier_path = 'lib/models/SentimentClassifier.pkl' +with open(classifier_path, 'rb') as f: + model.classifier = pickle.load(f) + +vectorizer_path = 'lib/models/tfidf_vectorizer.pkl' +with open(vectorizer_path, 'rb') as f: + model.vectorizer = pickle.load(f) + +#parse args +parser = reqparse.RequestParser() +parser.add_argument('query') + +class PredictUserSentiments(Resource): + def get(self): + args = parser.parse_args() + user_query = args['query'] + + vectorize_userq = model.transform_vectorizer(np.array([user_query])) + prediction = model.predict_sentiment(vectorize_userq) + predict_probability = model.predict_proba(vectorize_userq) + + if prediction == 0: + predicted_sentiment = 'Negative' + else: + predicted_sentiment = 'Positive' + + #confidence level + c_level = round(predict_probability[0], 3) + + #json obj + output_as_json = {'sentiment': predicted_sentiment, 'confidence': c_level} + + return output_as_json + +#add resource routes +api.add_resource(PredictUserSentiments, '/') + +#run app +if __name__ == '__main__': + app.run(debug=True) diff --git a/Sentiment Classifier API/build_model.py b/Sentiment Classifier API/build_model.py new file mode 100644 index 0000000..498aaf2 --- /dev/null +++ b/Sentiment Classifier API/build_model.py @@ -0,0 +1,32 @@ +from model import SentimentClassifierModel +import numpy as np +import pandas as pd +from sklearn.model_selection import train_test_split + + +def build_model(): + model = SentimentClassifierModel() + + with open('D:/Projects/REST APIs Flask/NLP Sentiment Classifier API/lib/data/train.tsv') as f: + data = pd.read_csv(f, sep='\t') + data = data.replace(to_replace = 'None', value = np.nan).dropna() + + positive_negative = data[(data['Sentiment'] == 0) | (data['Sentiment'] == 4)] + + positive_negative['Binary'] = positive_negative.apply(lambda x : 0 if x['Sentiment'] == 0 else 1, axis=1) + + model.fit_vectorizer(positive_negative.loc[:,'Phrase']) + + x = model.transform_vectorizer(positive_negative.loc[:,'Phrase']) + y = positive_negative.loc[:, 'Binary'] + + x_train, x_test, y_train, y_test = train_test_split(x,y) + + model.train(x_train, y_train) + print("Model trained successfully!") + + model.pickle_classifier() + model.pickle_tfidfvec() + +if __name__ == "__main__": + build_model() diff --git a/Sentiment Classifier API/model.py b/Sentiment Classifier API/model.py new file mode 100644 index 0000000..5b8dfc3 --- /dev/null +++ b/Sentiment Classifier API/model.py @@ -0,0 +1,43 @@ +#importing dependencies +from sklearn.naive_bayes import MultinomialNB +from sklearn.feature_extraction.text import TfidfVectorizer +import pickle + +class SentimentClassifierModel(object): + + def __init__(self): + self.classifier = MultinomialNB() + self.vectorizer = TfidfVectorizer() + + def fit_vectorizer(self, x): + #fit tfidf to corpus + self.vectorizer.fit(x) + + def transform_vectorizer(self,x): + #transform corpus to vector matrix (sparse tfidf matx) + transform_x = self.vectorizer.transform(x) + return transform_x + + def train(self, x, y): + #trains the text classifier to associate target labels(sentiment scores) with matrix labels + self.classifier.fit(x,y) + + def predict_proba(self,x): + #returns conditional probability of class y (target) wrt x for bin class 1 + proba_y = self.classifier.predict_proba(x) + return proba_y[:,1] + + def predict_sentiment(self,x): + y_pred = self.classifier.predict(x) + return y_pred + + def pickle_tfidfvec(self, path = 'lib/models/tfidf_vectorizer.pkl'): + with open(path, 'wb') as f: + pickle.dump(self.vectorizer, f) + print("Pickled tfidf-vectorizer at {}".format(path)) + + def pickle_classifier(self, path ='lib/models/SentimentClassifier.pkl'): + with open(path, 'wb') as f: + pickle.dump(self.classifier, f) + print("Pickled classifier at {}".format(path)) +