Movie Review Sentiment Analysis is a very normal example for text analysis, we can using this analysis to help us predict the sentiment of a movie review, and even construct a recommendation system to help us choose a movie.

A dataset consisting of 50,000 IMDB movie reviews, where each review is labelled as positive or negative. The goal is to build a binary classification model to predict the sentiment of a movie review.

We first construct DT (DocumentTerm) matrix. We use all movie reviews to get word list and then construct DT matrix.

train = read.table("C:/Users/ZhouZhen/Downloads/alldata.tsv", stringsAsFactors = FALSE,header = TRUE, encoding="UTF-16LE")
train$review = gsub('<.*?>', ' ', train$review)
head(train)
##   id sentiment score
## 1  1         1    10
## 2  2         0     2
## 3  3         0     4
## 4  4         0     2
## 5  5         1     7
## 6  6         1     8
##                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            review
## 1                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               Naturally in a film who's main themes are of mortality, nostalgia, and loss of innocence it is perhaps not surprising that it is rated more highly by older viewers than younger ones. However there is a craftsmanship and completeness to the film which anyone can enjoy. The pace is steady and constant, the characters full and engaging, the relationships and interactions natural showing that you do not need floods of tears to show emotion, screams to show fear, shouting to show dispute or violence to show anger. Naturally Joyce's short story lends the film a ready made structure as perfect as a polished diamond, but the small changes Huston makes such as the inclusion of the poem fit in neatly. It is truly a masterpiece of tact, subtlety and overwhelming beauty.
## 2                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          This movie is a disaster within a disaster film. It is full of great action scenes, which are only meaningful if you throw away all sense of reality. Let's see, word to the wise, lava burns you; steam burns you. You can't stand next to lava. Diverting a minor lava flow is difficult, let alone a significant one. Scares me to think that some might actually believe what they saw in this movie.  Even worse is the significant amount of talent that went into making this film. I mean the acting is actually very good. The effects are above average. Hard to believe somebody read the scripts for this and allowed all this talent to be wasted. I guess my suggestion would be that if this movie is about to start on TV ... look away! It is like a train wreck: it is so awful that once you know what is coming, you just have to watch. Look away and spend your time on more meaningful content.
## 3                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          All in all, this is a movie for kids. We saw it tonight and my child loved it. At one point my kid's excitement was so great that sitting was impossible. However, I am a great fan of A.A. Milne's books which are very subtle and hide a wry intelligence behind the childlike quality of its leading characters. This film was not subtle. It seems a shame that Disney cannot see the benefit of making movies from more of the stories contained in those pages, although perhaps, it doesn't have the permission to use them. I found myself wishing the theater was replaying "Winnie-the-Pooh and Tigger too", instead. The characters voices were very good. I was only really bothered by Kanga. The music, however, was twice as loud in parts than the dialog, and incongruous to the film.  As for the story, it was a bit preachy and militant in tone. Overall, I was disappointed, but I would go again just to see the same excitement on my child's face.  I liked Lumpy's laugh....
## 4                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   Afraid of the Dark left me with the impression that several different screenplays were written, all too short for a feature length film, then spliced together clumsily into this Frankenstein's monster.  At his best, the protagonist, Lucas, is creepy. As hard as it is to draw a bead on the secondary characters, they're far more sympathetic.  Afraid of the Dark could have achieved mediocrity had it taken just one approach and seen it through -- and had it made Lucas simply psychotic and confused instead of ghoulish and off-putting. I wanted to see him packed off into an asylum so the rest of the characters could have a normal life.
## 5                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          A very accurate depiction of small time mob life filmed in New Jersey. The story, characters and script are believable but the acting drops the ball. Still, it's worth watching, especially for the strong images, some still with me even though I first viewed this 25 years ago.  A young hood steps up and starts doing bigger things (tries to) but these things keep going wrong, leading the local boss to suspect that his end is being skimmed off, not a good place to be if you enjoy your health, or life.  This is the film that introduced Joe Pesce to Martin Scorsese. Also present is that perennial screen wise guy, Frank Vincent. Strong on characterizations and visuals. Sound muddled and much of the acting is amateurish, but a great story.
## 6 ...as valuable as King Tut's tomb! (OK, maybe not THAT valuable, but worth hunting down if you can). I notice no one has commented on this movie for some years, and I hope a fresh post will spark some new comments. This is a film that I remembered only snippets of from childhood, and only saw recently when I tired of waiting for Fox to honour its own past, and hunted down the Korean DVD (in English, but with unremovable Korean subtitles). I won't go through another long plot description - suffice to say that seeing it for the first time in its proper widescreen format left me agape at the vistas and the scope of the film. The matte paintings still hold up, and the palace sets are truly breathtaking. But it is the smaller scale details that lend this film its depth and richness, offering a glimpse into the lifestyles of Egypt's poor as well as its elite. The bazaars, hovels, docks, embalming houses, and taverns are as fascinating as Pharaoh's throne room. While errors abound on the large scale (most notably the dynastic succession), the details are more meticulously researched than the vast majority of Hollywood's films. Visually, it's not without its flaws - the interiors are often too overly lit and colourful to blend seamlessly with the exteriors. Nevertheless, this is a movie that should be credited for being as audacious in the small as it is in the large. Tedious? In parts, absolutely. Overacted? Underacted? Yes, both - though 'understated' might be a more apt description. Too long? Absolutely not. I wished they had spent more time with Sinuhe's experiences in the House of Death, and among the Hittites, and less with his 'romance' with Nefer, though. Historically inaccurate? Yes, that too, but so was Shakespeare. Nobody chastises him for it. I appreciate historical accuracy as much as the next guy, but ultimately it has to be remembered that cinema is theater, not a history lesson.
stop_words = c("i", "me", "my", "myself", 
               "we", "our", "ours", "ourselves", 
               "you", "your", "yours", 
               "their", "they", "his", "her", 
               "she", "he", "a", "an", "and",
               "is", "was", "are", "were", 
               "him", "himself", "has", "have", 
               "it", "its", "the", "us")

We use stop words everyday, stop words are the articles, prepositions, and phrases that connect keywords together and help us form complete, coherent sentences. We use 32 stop words in this task.

it_train = itoken(train$review,
                  preprocessor = tolower, 
                  tokenizer = word_tokenizer)
tmp.vocab = create_vocabulary(it_train, 
                              stopwords = stop_words, 
                              ngram = c(1L,4L))

The code above is to create vocabulary, and the code below is to filters the input vocabulary and throws out very frequent and very infrequent terms.

tmp.vocab = prune_vocabulary(tmp.vocab, term_count_min = 10,
                             doc_proportion_max = 0.5,
                             doc_proportion_min = 0.001)
dtm_train  = create_dtm(it_train, vocab_vectorizer(tmp.vocab))

dtm_train is my DT matrix.

I just want to get a vocabulary which size is less than 1K, so I use Lasso to trim the vocabulary size to 1K.

By using Lasso, I find that 36th column is the biggest column whose df less than 1K.

set.seed(4358)
tmpfit = glmnet(x = dtm_train, 
                y = train$sentiment, 
                alpha = 1,
                family='binomial')
myvocab = colnames(dtm_train)[which(tmpfit$beta[, 36] != 0)]

The code above is the way how I construct my word list.

Check the word list, we can find that

v.size = dim(dtm_train)[2]
ytrain = train$sentiment

summ = matrix(0, nrow=v.size, ncol=4)
summ[,1] = colapply_simple_triplet_matrix(
  as.simple_triplet_matrix(dtm_train[ytrain==1, ]), mean)
summ[,2] = colapply_simple_triplet_matrix(
  as.simple_triplet_matrix(dtm_train[ytrain==1, ]), var)
summ[,3] = colapply_simple_triplet_matrix(
  as.simple_triplet_matrix(dtm_train[ytrain==0, ]), mean)
summ[,4] = colapply_simple_triplet_matrix(
  as.simple_triplet_matrix(dtm_train[ytrain==0, ]), var)

n1 = sum(ytrain); 
n = length(ytrain)
n0 = n - n1

myp = (summ[,1] - summ[,3])/
  sqrt(summ[,2]/n1 + summ[,4]/n0)
words = colnames(dtm_train)
id = order(abs(myp), decreasing=TRUE)[1:2000]
pos.list = words[id[myp[id]>0]]
neg.list = words[id[myp[id]<0]]

Here is the first 10 words which is recognized as positive word by using a two-sample t-test

head(pos.list,20)
##  [1] "great"       "excellent"   "wonderful"   "best"        "of_best"    
##  [6] "one_of_best" "love"        "perfect"     "loved"       "amazing"    
## [11] "beautiful"   "superb"      "well"        "favorite"    "brilliant"  
## [16] "highly"      "life"        "must_see"    "also"        "fantastic"

And also the first 10 negative words is

head(neg.list,20)
##  [1] "bad"      "worst"    "waste"    "awful"    "terrible" "worse"   
##  [7] "boring"   "no"       "stupid"   "nothing"  "waste_of" "poor"    
## [13] "horrible" "of_worst" "minutes"  "even"     "so_bad"   "just"    
## [19] "crap"     "supposed"

Then we load the testing data set and training data set.

data=train
testIDs <- read.csv("C:/Users/ZhouZhen/Downloads/project3_splits.csv", header = TRUE)

j=1
dir.create(paste("split_", j, sep=""))
## Warning in dir.create(paste("split_", j, sep = "")): 'split_1' already exists
train <- data[-testIDs[,j], c("id", "sentiment", "review") ]
test <- data[testIDs[,j], c("id", "review")]
test.y <- data[testIDs[,j], c("id", "sentiment", "score")]

We should create DT matrix for training data and test data either.

I use ridge regression to do the prediction

train$review <- gsub('<.*?>', ' ', train$review)
it_train = itoken(train$review,
                    preprocessor = tolower, 
                    tokenizer = word_tokenizer)
vectorizer = vocab_vectorizer(create_vocabulary(myvocab, 
                                                  ngram = c(1L, 2L)))
dtm_train = create_dtm(it_train, vectorizer)
  
fit_dtm=glmnet(dtm_train, y=train$sentiment,alpha=0)

  
  
train$review <- gsub('<.*?>', ' ', test$review)
it_test = itoken(test$review,
                    preprocessor = tolower, 
                    tokenizer = word_tokenizer)

dtm_test = create_dtm(it_test, vectorizer)
output=predict(fit_dtm, newx = dtm_test,type = "class",s = 0)
output=cbind(test$id,output)
colnames(output)=c("id","prob")
library(pROC)
## Type 'citation("pROC")' for a citation.
## 
## Attaching package: 'pROC'
## The following objects are masked from 'package:stats':
## 
##     cov, smooth, var
pred <- output
pred <- merge(pred, test.y, by="id")
roc_obj <- roc(pred$sentiment, pred$prob)
## Setting levels: control = 0, case = 1
## Setting direction: controls < cases
pROC::auc(roc_obj)
## Area under the curve: 0.9646

By using AUC to do code evaluation, finally auc is 0.9645, which is great for this task.

Part of the code was provided by Prof. liangfang