《羞羞的铁拳》好不好看 8万观众说了算——文本情感分析(机器学习)

《羞羞的铁拳》好不好看 8万观众说了算——文本情感分析(机器学习)

伟楠伟楠
本文为 Part 2~~~~ Part 1 在此:《羞羞的铁拳》好不好看 8万观众说了算——EDA



〇、 写在前面

在上一篇《羞羞的铁拳》好不好看 8万观众说了算——EDA 中我们对数据进行了一个初步的探索,完成了一个EDA的流程。那么接下来,在Part 2中呢,我们就要正式开始用机器学习做情感分类了。


一、 场景应用

那首先我们先来看看情感分类有什么用。情感分析呢,也成为观点挖掘,是目前NLP领域一个非常热门的分支。它主要是通过分析文本的情感倾向,结合业务来做一些改进等。

目前在电商领域情感分析应用的比较广泛,比如马上就双十一了,大家经常逛淘宝可能会在买东西前先看一看普遍的评论怎么样。这时候不知道大家有没有留意到,在评论的最上面经常会出现一些关键词,并用红色或绿色标明了大家觉得这个商品好不好。那么究竟怎么判断一天评论是红色还是绿色呢,这就是通过训练好的情感分类模型来进行判别了。当然淘宝这个还涉及到了文本聚类,关键词提取等等,这些就不在我们本文范围之内了(报告老师 这些超纲了),等以后在来搞这一块吧。

淘宝评论

那么电商有这样的应用,可在电影领域呢?毕竟我们这次的数据集是豆瓣影评呀。嗯,我设想出来了三个应用场景(拍脑瓜想的,没有严谨的思考哈):

  • 用于社交平台的舆论分析
  • 对预告片评论分类
  • 利用好评-差评比结合票房建模,预测舆论对于票房的影响情况

社交平台的舆论分析主要是可以用来判断某个社交平台的用户对于本片的态度,大家知道不同的社交平台其目标人群是不同,自然价值观也是不同的(例如知乎、快手、微博的用户群体都是不同的)。那么当一部电影需要公关的时候,它可以根据不同平台的倾向性,更好的调配自己的资源(水军???)。比如某某明星出事了,可能微博上都是他的粉丝,大家都很支持他,而知乎上都是分析骂他的人,这个时候公关就应该把精力更多的放在知乎上来为明星洗地。而微博则可以不用投入太多资源,因为就算你不洗,粉丝都是支持他的。

预告片评论的话,可以分析出大家对于这部影片的期待程度。可以为上映前的宣传策略做指导,进行精准营销。同时也可以给影院排片比例做指导。

票房这点的话,主要是想着了解舆论对于票房的影响程度,通过舆论也可以对票房做一个预测,同样是给影院在决定拍片比例以及档期时间提供一定的指导。毕竟《逐梦演艺圈》的毕导都说了,“一个青年导演花十二年心血认认真真给中国拍电影,被豆瓣一天毁了”,可见舆论多厉害啊。


二、 数据预处理


  • 词袋模型(bag-of-words model)

我们使用《夏洛特》和《驴得水》合并来的数据进行建模,之后在铁拳上看看效果如何。但在此之前,先给大家介绍下一个非常有用的模型——词袋模型

首先对于NLP领域来说,词袋模型(bag-of-words model)是文本挖掘中一个非常成熟的模型。它将文本以数值特征向量的形式来表示出来,简单的描述下:

  1. 我们在整个文档中为每个词汇创建唯一标记,如单词。
  2. 为每个文档构建一个包含每个单词在此文档中出现次数的特征向量。

具体的网上有很多文章讲得很详细,大家感兴趣的话可以自己去看看。


简单说下词袋后,我们要接着对我们的数据进行一些处理,首先就是要去除停用词

什么是停用词呢?就是类似于“的”“哦”“啊”“是”这些没有太多信息量的介词、助词等。因为这些词不带有多少信息量,而且会对我们的模型造成干扰,也会增加我们的计算成本,所以我们在一开始就要先把他们去掉。网上有很多中文的停用词集合,我也自己整理收集了一份感觉是目前最全的停用词表,大家如果有需要的话,我发给大家。

部分停用词

这之后呢,中文NLP跟英文NLP最大的不同就是中文要先进行分词处理,而英文则不用。那什么是分词,说白了就是小学语文经常考的断句。例如:“今天天气真好”,我们正常人会把它断句成:“今天/天气/真/好”,相信不会有人断成:“今/天天气/真好”吧。

至于为什么中文要分词,英文却不用呢?其实大家想想“what a nice day today”,我们会怎么断句呢?没错当然是通过空格了,英语天生就有空格来作为它的分词符,而中文是没有的,所以对于中文我们先要进行分词。分词的好坏直接决定了后面文本分析的准确与否。

那如何实现中文分词呢?大致可分为

  • 机械分词、
  • 统计分词、
  • 机器学习分词

而机器学习分词比较常见的方法是隐马尔可夫模型(Hidden Markov Model,HMM)条件随机场(Conditional Random Field,CRF),具体的就不展开说了,超出我们这篇文章的范畴了,感兴趣的同学可以自己找一下相关的论文来看哈。

目前中文分词系统有开源的结巴分词、中科院的ICTCLAS、哈工大的ltp等,这里我们选择用结巴分词,结巴分词也是基于HMM的Viterbi算法实现的。

我们先写好几个方法,用了分词及去除停用词。

然而对于一些特殊的词或者人名什么的,可能结巴分词不能很好的正确划分出来,最好自己先提前添加一个自定义的用户词典

  • 构建标签

我们说了情感分类是一个有监督的分类问题,所以我们还要构建我们的标签。这也就是选择豆瓣的好处,因为豆瓣上每个评论都会带有观众对于这部电影的打分,而这些打分反应出了观众对于这部电影的情感。

我们取4星及以上的作为标签“1”3星及以下的为标签“0”,构造sentiment列

现在就可以将我们的评论数据进行分词了。

之后按照惯例将数据划分为训练集和测试集

至此我们对于数据的初步处理就完成了,接下来可以将数据扔进模型里跑一跑了。处理好的数据大致如下:

三、 tf-idf

等等,我刚刚好像说“可以将数据扔进模型里跑一跑了”,然而实际上大家尝试下就会发现还不行,模型不认这些文本啊。这就要涉及到将文本数据转换成为数值格式了。

该怎么做呢?我们可以使用sklearn中的Count-Vectorizer来实现,它以文本数据作为输入,返回的便是我们需要的词袋模型。不过这里我们暂时先不使用这个方法,因为....我懒,我要走捷径。至于什么捷径呢,先按下不表。

在此之前我先给大家再介绍一个文本挖掘领域用到烂的不能再烂的方法了,但是确实又十分方便好用。这个...招不在新,管用就行嘛。我们隆重欢迎 tf-idf(词频-逆文档频率) 闪亮登场。

什么是tf-idf呢,顾名思义,大家光看名字也能猜到些些了,其实很容易理解。tf就是词频,表示一个词在文档中出现的频率。这里有一个假设,就是如果一个词在文章中出现的次数越多,说明它越能代表这篇文章。这么说是有道理的,然而实际操作中就会发现,出现最多的基本上都是类似于“的”、“是”、“哦”等没有实际信息量的词汇。

这时候该怎么办呢,就要派我们的idf出场了。逆文档频率,意为文档的总数与包含某词汇的文档数量的比值。通俗点说也就是一个词在越多的文档中出现就意味着这个词越不重要,你就是个大众货。这样就能有效降低像“的”、“是”等词的权重。

tf-idf就是将两项相乘,找出最能代表一篇文章的词。大家可以想想是不是基本上每篇文章都会出现大量的“的”“是”等词,虽然他们出现的频率很高但是他们完全没法代表一篇文章的内容。而像我这段描述中,‘tf’'idf'等词在这段中出现的次数虽然不是最多但还算可以,可是在别的段落中基本上却没有出现过,所以就可以认为最能代表我这段话内容的词应该就是‘tf’'idf'了。 这么说大家应该明白了吧~

这里还有一篇阮一峰老师写的文章,讲解的很透彻大家可以学习下~ruanyifeng.com/blog/201

嗯,那么回到刚刚说的捷径上来,sklearn提供了一个很方便的工具来将文本转换为tf-idf矩阵——TfidfVectorizer。它可以直接将文本转换成tf-idf矩阵,而不用先通过Count-Vectorizer转换为特征向量,再用TfidfTransformer转换成tf-idf矩阵这么麻烦

现在将我们的评论数据转换成tf-idf矩阵。这里还要在提一下ngram_range这个参数。它是用来设定n元祖(n_gram)模型的n。n_gram是什么意思呢,直接举个例子大家就明白了。

这有一句话:What a nice day today.

  • 1-gram:"what","a","nice","day","today"
  • 2-gram:"what a","a nice","nice day","day today"

那么做完这些工作后,此时我们的文本数据就已经被转换成了tf-idf矩阵了,这是一个异常稀疏的矩阵,因为每个文档中出现的单词数量都只是整个词袋中的一个很小很小的子集,所以特征向量中的绝大部分元素都是0。


四、 特征选择

我们将文本转换成特征向量后,会发现其特征具有非常高的维度。这么多的特征要如何筛选呢。我见到很多人是直接用tfidf的值来进行特征筛选的,个人感觉这样是不太好的,应该通过卡方检验或者信息增益等方法来选择特征。至于为什么,这里有一篇文章阐述的比较清楚,我就不另外解释了。blogjava.net/zhenandaci

在这里我使用卡方检验结合 feature_selection 中的 SelectKBest 来做特征选择。我们将k的取值画出来,可以看到当k等于40000万左右的时候效果最好

所以就让我们愉快的利用卡方检验取前40000个特征作为我们最终的训练集吧。

可以看到这是一个 (155936*40000)的矩阵,共有1472109个元素,可以说是非常稀疏

当然,特征工程的方法非常多,这是一门非常高深的学问。毕竟我们常说“特征决定模型的上限,调参只是无限逼近这个上限”。选择特征的方法也要根据不同的场景做变化。利用随机森林跑一遍模型看特征重要性也是一个非常好的方法~~


五、 真·训练模型

这回真的真的可以直接把数据丢进模型跑跑了,不骗你们。【流下了激动的泪水】

有了训练数据,有了标签,那我们现在的任务就可以转换成一个有监督的二分类任务了。进行情感分类的时候,我们将观众的影评分为正向负向的情感。这里我们使用朴素贝叶斯逻辑斯蒂回归两个模型来做分类,对比下效果。通常情况下,朴素贝叶斯对于文本数据的效果一般都很不错。我们将筛选好的tfidf特征作为训练输入数据,将对应的情感值作为标签,进行训练。

  • 朴素贝叶斯

先用朴素贝叶斯看看效果,调参我用了GridSearchCV网格搜索自动调参,交叉验证cv取10折,scoring为‘roc_auc’。

在训练集上得分0.88,看起来效果还行吧,那么在看看测试集上的表现如何咧。

测试集0.806,也还好,可以接受。那我们生成混淆矩阵看看recall、Precision和f1-score吧

在测试集上正例的recall有0.92,precision也有0.83,f1为0.87,看起来还行。

那在看看ROC曲线


  • 逻辑斯蒂回归

接下来看看LogisticRegression的效果,同样采用GridSearchCV自动调参,交叉验证取10,scoring=‘roc_auc’

训练集上得分0.87,稍弱于贝叶斯童鞋。再来看看测试集上

测试集得分0.81,要比贝叶斯来的好一点。

同样接下来看看混淆矩阵,在测试集上正例的recall有0.92,precision也有0.84,f1为0.88,略微好于朴素贝叶斯。

ROC曲线如下:

花费了那么长时间来训练模型,如果不把模型保存下来留着以后再用的话,就太对不起家里的电费了,是吧~


六、 在《羞羞的铁拳》上测试效果


将我们已经训练好的模型,在实际中测试下看看效果如何。用了我们上篇探索了半天的《羞羞的铁拳》来测试吧。

首先别忘了要先transform下:

  • 朴素贝叶斯

朴素贝叶斯的话,得分0.77。唔,不是特别的好,估计是训练样本太小了,毕竟才只拿了两部电影的数据来做训练。

混淆矩阵和ROC在这,随便看看吧 哈哈哈

混淆矩阵
ROC
  • 逻辑斯蒂回归

LR效果也差不多,还是训练数据太少了。

附上混淆矩阵和ROC吧

混淆矩阵
ROC

七、 总结

这次分析到此就结束了,总共分为两个部分:

  • EDA
  • 文本情感分析

《羞羞的铁拳》好不好看 8万观众说了算——EDA中,对数据进行了初步的探索,看了下各星级的人数分布、电影热度随时间变化、各星级词云等,算是对数据有个整体的认知吧。

在本部分中则针对如何建立一个文本情感分类器的流程做了一个演示,主要为以下几点:

  • 数据处理(分词、去停止词)
  • 构建tf-idf矩阵
  • 卡方检验筛选特征
  • 建立模型
  • 模型调优、评估

最后朴素贝叶斯模型在训练集上accuracy为0.88,测试集上0.806,在实际预测《羞羞的铁拳》中为0.77。

逻辑斯蒂回归模型在训练集上accuracy为0.87,测试集上0.81,在实际预测《羞羞的铁拳》中为0.75。


说下自己觉得今后还可以改进的地方,

  1. 首先,在实际数据中跑出来的效果并不是特别的好,这个我在前面也提到了,跟采集的数据太少了有关。毕竟总共只采集了两部电影来做训练集,这肯定是远远不够的。而且我还是别有心机的选择了同为开心麻花的电影来做测试,毕竟同样导演同样风格的电影,预测的会更准一些。如果换一部电影,比如说《战狼2》估计最后的得分会更低。所以如果在真实项目中的话,这个原始数据肯定要采集的多很多倍才行了。
  2. 其实词袋模型虽然非常经典但是也还是有缺陷的,比如说它忽略了词与词之间的关系,把每个词都拆分成了单独的存在。可以使用LDA主题模型(隐含狄利克雷分布)来一定程度上解决此问题,LDA主题模型就是用来挖掘出意义相关的语句的。需要注意的是这里的LDA是隐含狄利克雷分布(Latent Dieichlet Allocaion,LDA)而非我们常用来降维的线性判别分析LDA(Linear Discriminant Analysis,LDA),大家千万不要搞混了。我之前见到有人把这两个混为一谈了,可真真是贻笑大方啊~~~
  3. 像本篇使用的是经典的文本分析方法,现在深度学习的流行,让使用深度学习进行文本分析变得非常热门,比如Google开源Word2Vec。以后有机会的话,可以再尝试写一篇深度学习用于文本分析的。非常羡慕大神们用RNN等搞出来的各种各种让人惊艳的作品啊,比如续写冰与火的那个~~感觉好有意思~看来未来的道路还很长啊~~~




广告时间:欢迎大家看看我以前的文章哈,顺便关注下专栏,点个赞呗~

值得一去的饭店在哪里?——让数据分析告诉你

《羞羞的铁拳》好不好看 8万观众说了算——EDA

专栏:数据故事会~

「千万别给钱 叔叔阿姨我不要 真的 点赞就好」
还没有人赞赏,快来当第一个赞赏的人吧!
文章被以下专栏收录
18 条评论
推荐阅读