京东商品评论情感分析:数据采集与词向量构造方法
最近实习期间在做一个对新闻文本情感分析的项目。在此,用京东的商品评论练手,从 数据采集 到模型实现完整地写一遍,以备未来回顾所需。事实上,我采用的方法并不困难,甚至有点naive,所以权且作为练手吧。
本文代码在公众号 datadw 里 回复 京东 即可获取。
数据采集
在这里为了避免人工标注的麻烦,使用的是京东iPad的用户评论
https://item.jd.com/4675696.html#none
事实上,NLP情感分析中最花时间的就是人工标注。
仔细查看调试台可以很容易地发现商品的评论信息都是用json来传递的。如下:https://club.jd.com/comment/productPageComments.action?callback=fetchJSON_comment98vv37157&productId=4675696&score=5&sortType=6&page=0&pageSize=10&isShadowSku=0&fold=1
这个URL其实还是比较容易看出设计者的思路的。productId是商品对应的ID,score为用户对商品的评分,pageSize应该是一个请求发回的评论数。在实践中发现这种pageSize一般是不可以无限大的,也就是你别想着把pageSize写得很大,然后就可以一个请求返回一大堆数据。我的做法就是把pageSize写得一般大
(^-^)
,然后不断地递增page来不断地爬去数据。
score的规则如下: * 1:差评 * 2:中评 * 3:好评 * 5:追评
把这个URL放在浏览器的搜索地址里就可以得到返回的相应JSON数据了。这里就不展示了,自己去看吧。一开始你可能会觉得这个json,但只要仔细看看就知道你想要的数据在哪了。你要知道写网站的程序员也是程序员而已,程序员都喜欢工整的东西,因为“简单源于工整”,所以你只要发现他实现工整的方法,你就可以很简单地获取相应的数据了。
事实上,京东对于网络爬虫是非常宽容的,就算不加任何的速度控制也可以毫无阻碍地完成数据的采集工作。这里建议使用Python3.5,因为3.5对中文的支持比较好,另外需要额外下载Request库。这就不再赘述了。
构造词向量的方法
TF-IDF
这里我采用的是,利用TF-IDF来计算词库中最具代表性的词。
概念
TF-IDF(term frequency–inverse document frequency)是一种用于资讯检索与资讯探勘的常用加权技术。TF-IDF是一种统计方法,用以评估一字词对于一个文件集或一个语料库中的其中一份文件的重要程度。字词的重要性随着它在文件中出现的次数成正比增加,但同时会随着它在语料库中出现的频率成反比下降。TF-IDF加权的各种形式常被搜寻引擎应用,作为文件与用户查询之间相关程度的度量或评级。除了TF-IDF以外,因特网上的搜寻引擎还会使用基于连结分析的评级方法,以确定文件在搜寻结果中出现的顺序。
原理
在一份给定的文件里,
词频 (term frequency, TF)
指的是某一个给定的词语在该文件中出现的次数。这个数字通常会被归一化(分子一般小于分母 区别于IDF),以防止它偏向长的文件。(同一个词语在长文件里可能会比短文件有更高的词频,而不管该词语重要与否。)
逆向文件频率 (inverse document frequency, IDF)
是一个词语普遍重要性的度量。某一特定词语的IDF,可以由总文件数目除以包含该词语之文件的数目,再将得到的商取对数得到。
某一特定文件内的高词语频率,以及该词语在整个文件集合中的低文件频率,可以产生出高权重的TF-IDF。因此,
TF-IDF倾向于过滤掉常见的词语,保留重要的词语
。
TFIDF的主要思想是:如果某个词或短语在一篇文章中出现的频率TF高,并且在其他文章中很少出现,则认为此词或者短语具有很好的类别区分能力,适合用来分类。TFIDF实际上是:TF * IDF,TF词频(Term Frequency),IDF反文档频率(Inverse Document Frequency)。TF表示词条在文档d中出现的频率(另一说:TF词频(Term Frequency)指的是某一个给定的词语在该文件中出现的次数)。IDF的主要思想是:
如果包含词条t的文档越少,也就是n越小,IDF越大,则说明词条t具有很好的类别区分能力
。如果某一类文档C中包含词条t的文档数为m,而其它类包含t的文档总数为k,显然所有包含t的文档数n=m+k,当m大的时候,n也大,按照IDF公式得到的IDF的值会小,就说明该词条t类别区分能力不强。(另一说:IDF反文档频率(Inverse Document Frequency)是指果包含词条的文档越少,IDF越大,则说明词条具有很好的类别区分能力。)但是实际上,如果一个词条在一个类的文档中频繁出现,则说明该词条能够很好代表这个类的文本的特征,这样的词条应该给它们赋予较高的权重,并选来作为该类文本的特征词以区别与其它类文档。这就是IDF的不足之处.
在一份给定的文件里,词频(term frequency,TF)指的是某一个给定的词语在该文件中出现的频率。这个数字是对词数(term count)的归一化,以防止它偏向长的文件。(同一个词语在长文件里可能会比短文件有更高的词数,而不管该词语重要与否。)对于在某一特定文件里的词语 来说,它的重要性可表示为:
某一特定文件内的高词语频率,以及该词语在整个文件集合中的低文件频率,可以产生出高权重的TF-IDF。因此,TF-IDF倾向于过滤掉常见的词语,保留重要的词语。
补充说明
这里提出的TF-IDF的详细介绍只是给出了一种实现TF-IDF的一般做法,但是需要注意到的是,一般实现方法下的TF-IDF确实能够选出最能够区分不同文档的字词。但我希望做到的是,选出
最能用于区分不同情感的字词
,因此,这里我对公式做出了一点简单的修改。
在计算tf的时候,我认为,整个语料库里只有两种文档,一种是好评文档,一种是差评文档,不去细分每一条评论。具体见实现。
PMI 点相互信息
PMI(Pointwise Mutual Information)这个指标来衡量两个事物之间的相关性(比如两个词)。
在概率论中,我们知道,如果x跟y不相关,则
p(x,y)=p(x)p(y)
。二者相关性越大,则p(x,y)就相比于p(x)p(y)越大。用后面的式子可能更好理解,在y出现的情况下x出现的条件概率p(x|y)除以x本身出现的概率p(x),自然就表示x跟y的相关程度。
这里的log来自于信息论的理论,可以简单理解为,当对p(x)取log之后就将一个概率转换为了信息量(要再乘以-1将其变为正数),以2为底时可以简单理解为用多少个bits可以表示这个变量。
补充说明
与前面的TF-IDF一样,我希望选出的是对分类情感最有效的词,所以在这里对公式做出一点简单的修改。
PMI(word,pos)=logP(word,pos)P(pos)∗P(word)
pos表示的文档的情感,word表示某一个词。
分母表示同时在表现为pos情感和出现word词的概率。
完整代码
本文代码在公众号 datadw 里 回复 京东 即可获取。
在实现中,我们需要解决的就是
分词
和计算
词频
的问题了。
对于NLP来说,第一个问题就是要实现分词。市面上有很多的分词库,而且效果都还不错。比较难过的是,NLTK没有支持中文的分词方法,这里我使用的是jieba分词。jieba分词比较易用,而且可以很容易地添加自定义词库。在这个项目中,没有必须要加入自定义词库的需求,原因对于商品评论来说,没有非常特别的固定使用词。但是在我实习的项目,因为有很多固定用法的词,就非常有需要加自定义词库。
另外需要注意的是,虽然不用加入自定义词库,但还是需要删除一些“无效词”(stopwords),这里无效指的是对表达情感时,没有明确的情感指向但却是非常常用的词,也就是这些词的词频会非常高,因此这些词的TF-IDF仍然可能非常高,所以需要主动删除,以避免引入噪声。
实验结果
构造向量的时候,不可能直接把所有的词都用上,只能选择其中的一部分。这里我选择的是PMI最大的前30个词。
好评文档
不错
特别
差评文档
降价