这是我的影评,你猜我喜不喜欢这部电影

前言

最近拿了一份IMDb影评数据做练习,对(英文的)自然语言处理(Natural Language Processing,NLP)有了初步的认识,同时对特征工程和Stacking有了更深的理解。

这篇文章记录一下这次练习的过程。

一些需要说明的:

数据集

官方介绍:

This dataset contains sentences labelled with positive or negative sentiment.
The sentences come from three different websites/fields:
imdb.com
amazon.com
yelp.com
For each website, there exist 500 positive and 500 negative sentences. Those were selected randomly for larger datasets of reviews.

这里我只用到了IMDb的1000条影评,它具体长这样:

001 - IMDb影评数据

每一行表示一条影评,comment列显示影评的具体内容,is_pos列显示该观众喜欢(is_pos = 1)还是不喜欢(is_pos = 0)这部电影。

is_pos是此次分析的目标特征,其中,正面和负面影评各占50%:

002 - 正面与负面影评各占50%

我们需要做的是,根据这些已有的影评数据构建一个分类模型,这个模型能够根据一份影评返回一个结果:这位观众喜欢/不喜欢这部电影

文本特征提取

由于原始影评是非结构化的,算法不能对其直接进行学习,所以我们需要通过特征工程,提取出数据中的结构化信息,从而构建学习模型。

我基于原始文本,构建了43个新特征:

003 - 特征总览图

1. Features related to texts

  • 词数(number of words):#words,即一份影评总共有多少个词
  • 非重复词占比(ratio of unique words):#unique words / #words
  • Stop words占比(ratio of stopwords):#stop words / #words,其中,stop words指的是在英文中一些出现频率很高但没有特殊含义的常用词,比如a,the
  • 标点符号占比(ratio of punctuations):#punctuations / #words
  • 名词占比(ratio of nouns):#nouns / #words
  • 形容词占比(ratio of adj):#adj / #words
  • 动词占比(ratio of verbs):#verbs / #words
  • 标题词占比(ratio of title words):#title words / #words,其中,title words指的是首字母为大写的词
  • 平均词长(mean length of words):sum(length of each word in a text) / #words,即一份影评中,平均每个词的长度(平均每个词有多少个字母)
  • 文本字符长度(count of characters):len(text)
  • 积极词占比(ratio of positive words):#positive words / #words,其中,积极词词库出自这里

2. Features related to vectorizers

这部分的特征涉及以下几个概念:

  • Tokenization:文本词条(tokens)化,如将句子 "I like this move." 分解为 "I", "like", "this", "movie"
  • Count Vectorization:将一个语料库(corpus)转化为基于词频的矩阵,矩阵的每一行代表一个文本,每一列代表某个词条在该文本中出现的次数
  • TF-IDF: Term Frequency-Inverse Document Frequency,用于评估一字词对于一个语料库中的其中一份文件的重要程度,字词的重要性随着它在文件中出现的次数成正比增加,但同时会随着它在语料库中出现的频率成反比下降。
  • TF-IDF Vctorization:将一个语料库转化为基于TF-IDF值的矩阵,矩阵的每一行代表一个文本,每一列代表某个词条在该文本下的TF-IDF值
  • SVD:奇异值分解(Singular Value Decomposition),线性代数中的一种矩阵分解方法,在NLP中常与TF-IDF矩阵结合,进行特征降维(Feature Decomposition)
  • Stacking:集成学习方法(Ensemble Learning)的一种,思路大致如下:先通过不同算法得出一组预测值,再将这组预测值作为输入特征进行学习,从而得到数据的最终预测值(这里有一篇来自kaggle的文章,很好地解释了staking的实现过程)

了解了上述概念后,现在再回过头来看之前没有提到的特征:

  • 基于词频矩阵的NB预测值:通过count vectorization构建词频矩阵,将该矩阵作为输入特征,通过朴素贝叶斯(Naive Bayes,NB)构建目标变量预测值(is_pos = 1的概率),并将该预测值作为最终XGBoost模型的新特征
  • 基于词频矩阵矩阵的LR预测值:通过count vectorization构建词频矩阵,将该矩阵作为输入特征,通过逻辑回归(Logistic Regression,LR)构建目标变量预测值(is_pos = 1的概率),并将该预测值作为最终XGBoost模型的新特征
  • SVD features of TF-IDF metrix:通过TF-IDF vectorization构建TF-IDF矩阵,通过SVD将该矩阵降至30维,并将这30维向量作为最终XGBoost模型的新特征

结果分析

我在不同阶段使用不同特征组合、算法进行了建模,下面我将分别给出这些不同的建模结果,并在最后对这些结果进行综合对比,以期对特征工程、Stacking的作用管中窥豹。

1. XGBoost with features related to texts only

我首先用11个和文本自身相关的特征(词数、名词占比等)进行建模。使用的算法为XGBoost。

验证集(test set)预测效果:

  • LogLoss:0.59
  • AUC of ROC curve:0.75

可以看到,预测效果还是不错的,说明这些特征在一定程度上捕捉到了有用信息。

2. XGBoost with SVD features of TF-IDF metrix

接着用XGboost对那30个SVD特征建模。

验证集(test set)预测效果:

  • LogLoss:0.55
  • AUC of ROC curve:0.79

这些特征同样也捕捉到了有用信息,并且预测效果比之前那11个特征要稍好。注意,这里并不是说用了这30个SVD特征后,前面那11个特征就不需要了,二者捕捉到的可能是不同方面的信息。

3. NB using count matrix

接着用NB对词频矩阵构建分类预测模型。

验证集(test set)预测效果:

  • LogLoss:0.56
  • AUC of ROC curve:0.86

logloss和之前的结果相似,但auc提升了近9%,说明词频包含了相当一部分的有用信息,是很好的预测特征。

4. LR using count matrix

接下来用LR对词频矩阵构建分类预测模型。

验证集(test set)预测效果:

  • LogLoss:0.49
  • AUC of ROC curve:0.87

auc和之前相似,但logloss下降了12%,这同样表明词频是不错的预测特征。此外,LR和NB可能捕捉到了不同方面的信息,换句话说,把这两个模型下的预测值进行综合(stacking),也许能够得到更准确的预测结果。

5. XGBoost using all features

最后是使用全部43个特征进行建模的结果。学习算法为XGBoost。

验证集(test set)预测效果:

  • LogLoss:0.43
  • AUC of ROC curve:0.88

logloss低于之前的任何一个模型,auc高于之前的任何一个模型。

对比一下上述各个模型的ROC曲线:

004 - 各模型ROC曲线对比

可以看到,仅使用count matrix进行预测的NB和LR模型,预测结果已经很接近最终模型的预测结果,说明词频包含了大部分预测所需信息,且NB和LR对于这组数据而言,是有效的算法。

另一方面,最终模型的ROC曲线整体而言稍优于NB和LR模型,说明NB和LR在训练时,得到了数据不同方面的信息,而基于TF-IDF的SVD特征和其他基于文本本身的特征,进一步捕捉到了NB、LR无法获取的其他信息。通过对所有特征进行建模,最终的XGBoost模型综合了以上所有信息,从而提高了预测准确率。

再来看一下特征重要程度排名:

005 - 各特征在XGBoost中的重要程度排名

前4位分别是积极词占比(pos_word_ratio)、NB预测值(nb_ctv_pred)、LR预测值(lr_ctv_pred)和平均词长(mean_word_len)。其他特征也都在不同程度上发挥了作用。这进一步说明了特征工程和Stacking的重要性。

现在,看一下最终预测结果在测试集上的confusion matrix。

因为预测结果为is_pos = 1的概率值,所以我们需要先确定一个阈值,当概率值大于该阈值时,判定该影评为正面的(predictive is_pos = 1),否则为负面的(predictive is_pos = 0)。

基于ROC曲线返回的结果,选择True Positive Rate大于0.75下的第一个Threshold为该阈值,则当预测结果大于0.56时,判定该影评为正面的,否则为负面的。

由此得到的confusion matrix如下:

006 - 最终预测结果在测试集上的confusion matrix

预测集中共有300份影评,其中正面影评共有161份,负面影评共139份。在这些正面的影评中,有76.4%份影评被正确识别;在这些负面的影评中,有82.7%份影评被正确识别。整体而言,当拿到一份影评的时候,这个模型有0.793的概率能够正确辨别出这个观众喜欢还是不喜欢这部TA所点评的电影。(注意,不同的阈值返回不同的confusion matrix,以上只是其中一个阈值对应的结果。)

最后我们随机抽取出测试集上的几条影评来具体看一下模型给出的预测结果,从而对这个分类器有一个更直观的感受:

"This is an extraordinary film."
正面影评概率:0.724

"I couldn't take them seriously."
正面影评概率:0.098

"The plot doesn't hang together at all, and the acting is absolutely appalling."
正面影评概率:0.064

"My rating: just 3 out of 10."
正面影评概率:0.192

"I've seen soap operas more intelligent than this movie."
正面影评概率:0.504

"And I really did find them funny."
正面影评概率:0.563

"The story unfolds in 18th century Jutland and the use of period music played on period instruments is just one more fine touch."
正面影评概率:0.373

这个分类器给出的大多数概率值都比较合理,一个可能的原因是这个数据集本身就是经过筛选的,数据集里的影评基本上都“憎恶分明”,使得信息的提取相对容易。注意最后一条影评,我个人觉得这个影评是中性偏肯定的(is_pos也确实是1),但分类器只给出了0.373的概率,说明这个分类器的性能还有待提升。

结语

上面谈到的数据处理方法,灵感主要来源于Kaggle的某个基于NLP的分类竞赛(见前言中的“Tutorial来源”),比如构建词数、非重复词占比、平均词长这样的特征,比如将NB的预测值作为新特征后再二次建模。

这次练习的结果印证了Kaggle里两条百试不爽的法则:

  1. 一个数据挖掘任务的成功与否,很大程度上看特征工程做得好不好
  2. 能否进一步提升模型预测能力,stacking是一大秘诀

另外,有几个点我在这次的练习中没有涉及,但对于NLP来说非常值得一试,我在这里标出来供日后查缺补漏:

  1. Stemming and Lemmatization (related tutorial)
  2. Word Vectors and Deep Learning (related tutorial)

以上。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容