Movie Reviews Sentiment Analysis
In this Machine Learning Project, we’ll build binary classification that puts movie reviews texts into one of two categories — negative or positive sentiment. We’re going to have a brief look at the Bayes theorem and relax its requirements using the Naive assumption.
Let’s start by importing the Libraries :
import numpy as np import pandas as pd import re from nltk.corpus import stopwords from nltk.tokenize import word_tokenize from nltk.stem import SnowballStemmer from sklearn.feature_extraction.text import CountVectorizer from sklearn.model_selection import train_test_split from sklearn.naive_bayes import GaussianNB,MultinomialNB,BernoulliNB from sklearn.metrics import accuracy_score import pickle
Now let's read the dataset:
data = pd.read_csv('IMDB-Dataset.csv') print(data.shape) data.head()
(50000, 2)
review | sentiment | |
---|---|---|
0 | One of the other reviewers has mentioned that ... | positive |
1 | A wonderful little production. <br /><br />The... | positive |
2 | I thought this was a wonderful way to spend ti... | positive |
3 | Basically there's a family where a little boy ... | negative |
4 | Petter Mattei's "Love in the Time of Money" is... | positive |
data.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 50000 entries, 0 to 49999 Data columns (total 2 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 review 50000 non-null object 1 sentiment 50000 non-null object dtypes: object(2) memory usage: 781.4+ KB
No null values, Label encode sentiment to 1(positive) and 0(negative)
data.sentiment.value_counts()
negative 25000 positive 25000 Name: sentiment, dtype: int64
data.sentiment.replace('positive',1,inplace=True) data.sentiment.replace('negative',0,inplace=True) data.head(10)
review | sentiment | |
---|---|---|
0 | One of the other reviewers has mentioned that ... | 1 |
1 | A wonderful little production. <br /><br />The... | 1 |
2 | I thought this was a wonderful way to spend ti... | 1 |
3 | Basically there's a family where a little boy ... | 0 |
4 | Petter Mattei's "Love in the Time of Money" is... | 1 |
5 | Probably my all-time favorite movie, a story o... | 1 |
6 | I sure would like to see a resurrection of a u... | 1 |
7 | This show was an amazing, fresh & innovative i... | 0 |
8 | Encouraged by the positive comments about this... | 0 |
9 | If you like original gut wrenching laughter yo... | 1 |
def clean(text): cleaned = re.compile(r'<.*?>') return re.sub(cleaned,'',text) data.review = data.review.apply(clean) data.review[1]
'A wonderful little production. The filming technique is very unassuming- very old-time-BBC fashion and gives a comforting, and sometimes discomforting, sense of realism to the entire piece. The actors are extremely well chosen- Michael Sheen not only "has got all the polari" but he has all the voices down pat too! You can truly see the seamless editing guided by the references to Williams\' diary entries, not only is it well worth the watching but it is a terrificly written and performed piece. A masterful production about one of the great master\'s of comedy and his life. The realism really comes home with the little things: the fantasy of the guard which, rather than use the traditional \'dream\' techniques remains solid then disappears. It plays on our knowledge and our senses, particularly with the scenes concerning Orton and Halliwell and the sets (particularly of their flat with Halliwell\'s murals decorating every surface) are terribly well done.'
def is_special(text): rem = '' for i in text: if i.isalnum(): rem = rem + i else: rem = rem + ' ' return rem data.review = data.review.apply(is_special) data.review[1]
'A wonderful little production The filming technique is very unassuming very old time BBC fashion and gives a comforting and sometimes discomforting sense of realism to the entire piece The actors are extremely well chosen Michael Sheen not only has got all the polari but he has all the voices down pat too You can truly see the seamless editing guided by the references to Williams diary entries not only is it well worth the watching but it is a terrificly written and performed piece A masterful production about one of the great master s of comedy and his life The realism really comes home with the little things the fantasy of the guard which rather than use the traditional dream techniques remains solid then disappears It plays on our knowledge and our senses particularly with the scenes concerning Orton and Halliwell and the sets particularly of their flat with Halliwell s murals decorating every surface are terribly well done '
def to_lower(text): return text.lower() data.review = data.review.apply(to_lower) data.review[1]
'a wonderful little production the filming technique is very unassuming very old time bbc fashion and gives a comforting and sometimes discomforting sense of realism to the entire piece the actors are extremely well chosen michael sheen not only has got all the polari but he has all the voices down pat too you can truly see the seamless editing guided by the references to williams diary entries not only is it well worth the watching but it is a terrificly written and performed piece a masterful production about one of the great master s of comedy and his life the realism really comes home with the little things the fantasy of the guard which rather than use the traditional dream techniques remains solid then disappears it plays on our knowledge and our senses particularly with the scenes concerning orton and halliwell and the sets particularly of their flat with halliwell s murals decorating every surface are terribly well done '
import nltk nltk.download("stopwords") nltk.download('punkt') def rem_stopwords(text): stop_words = set(stopwords.words('english')) words = word_tokenize(text) return [w for w in words if w not in stop_words] data.review = data.review.apply(rem_stopwords) data.review[1]
[nltk_data] Downloading package stopwords to [nltk_data] /nltk_data... [nltk_data] Package stopwords is already up-to-date! [nltk_data] Downloading package punkt to /nltk_data... [nltk_data] Package punkt is already up-to-date!
['wonderful', 'little', 'production', 'filming', 'technique', 'unassuming', 'old', 'time', 'bbc', 'fashion', 'gives', 'comforting', 'sometimes', 'discomforting', 'sense', 'realism', 'entire', 'piece', 'actors', 'extremely', 'well', 'chosen', 'michael', 'sheen', 'got', 'polari', 'voices', 'pat', 'truly', 'see', 'seamless', 'editing', 'guided', 'references', 'williams', 'diary', 'entries', 'well', 'worth', 'watching', 'terrificly', 'written', 'performed', 'piece', 'masterful', 'production', 'one', 'great', 'master', 'comedy', 'life', 'realism', 'really', 'comes', 'home', 'little', 'things', 'fantasy', 'guard', 'rather', 'use', 'traditional', 'dream', 'techniques', 'remains', 'solid', 'disappears', 'plays', 'knowledge', 'senses', 'particularly', 'scenes', 'concerning', 'orton', 'halliwell', 'sets', 'particularly', 'flat', 'halliwell', 'murals', 'decorating', 'every', 'surface', 'terribly', 'well', 'done']
def stem_txt(text): ss = SnowballStemmer('english') return " ".join([ss.stem(w) for w in text]) data.review = data.review.apply(stem_txt) data.review[1] data.head()
review | sentiment | |
---|---|---|
0 | one review mention watch 1 oz episod hook righ... | 1 |
1 | wonder littl product film techniqu unassum old... | 1 |
2 | thought wonder way spend time hot summer weeke... | 1 |
3 | basic famili littl boy jake think zombi closet... | 0 |
4 | petter mattei love time money visual stun film... | 1 |
X = np.array(data.iloc[:,0].values) y = np.array(data.sentiment.values) cv = CountVectorizer(max_features = 1000) X = cv.fit_transform(data.review).toarray() print("X.shape = ",X.shape) print("y.shape = ",y.shape)
X.shape = (50000, 1000) y.shape = (50000,)
print(X)
[[0 0 0 ... 0 0 0] [0 0 0 ... 0 0 0] [0 0 0 ... 0 1 0] ... [0 0 0 ... 0 0 0] [0 0 1 ... 0 0 0] [0 0 0 ... 0 0 0]]
trainx,testx,trainy,testy = train_test_split(X,y,test_size=0.2,random_state=9) print("Train shapes : X = {}, y = {}".format(trainx.shape,trainy.shape)) print("Test shapes : X = {}, y = {}".format(testx.shape,testy.shape))
Train shapes : X = (40000, 1000), y = (40000,) Test shapes : X = (10000, 1000), y = (10000,)
gnb,mnb,bnb = GaussianNB(),MultinomialNB(alpha=1.0,fit_prior=True),BernoulliNB(alpha=1.0,fit_prior=True) gnb.fit(trainx,trainy) mnb.fit(trainx,trainy) bnb.fit(trainx,trainy)
BernoulliNB()
ypg = gnb.predict(testx) ypm = mnb.predict(testx) ypb = bnb.predict(testx) print("Gaussian = ",accuracy_score(testy,ypg)) print("Multinomial = ",accuracy_score(testy,ypm)) print("Bernoulli = ",accuracy_score(testy,ypb))
Gaussian = 0.7843 Multinomial = 0.831 Bernoulli = 0.8386
pickle.dump(bnb,open('model1.pkl','wb')) rev = """Terrible. Complete trash. Brainless tripe. Insulting to anyone who isn't an 8 year old fan boy. Im actually pretty disgusted that this movie is making the money it is - what does it say about the people who brainlessly hand over the hard earned cash to be 'entertained' in this fashion and then come here to leave a positive 8.8 review?? Oh yes, they are morons. Its the only sensible conclusion to draw. How anyone can rate this movie amongst the pantheon of great titles is beyond me. So trying to find something constructive to say about this title is hard...I enjoyed Iron Man? Tony Stark is an inspirational character in his own movies but here he is a pale shadow of that...About the only 'hook' this movie had into me was wondering when and if Iron Man would knock Captain America out...Oh how I wished he had :( What were these other characters anyways? Useless, bickering idiots who really couldn't organise happy times in a brewery. The film was a chaotic mish mash of action elements and failed 'set pieces'... I found the villain to be quite amusing. And now I give up. This movie is not robbing any more of my time but I felt I ought to contribute to restoring the obvious fake rating and reviews this movie has been getting on IMDb.""" f1 = clean(rev) f2 = is_special(f1) f3 = to_lower(f2) f4 = rem_stopwords(f3) f5 = stem_txt(f4) bow,words = [],word_tokenize(f5) for word in words: bow.append(words.count(word)) #np.array(bow).reshape(1,3000) #bow.shape word_dict = cv.vocabulary_ pickle.dump(word_dict,open('bow.pkl','wb'))
inp = [] for i in word_dict: inp.append(f5.count(i[0])) y_pred = bnb.predict(np.array(inp).reshape(1,1000)) print(y_pred)
[0]
0 mean negative.