文本情感分析
文本情感分析,又称为倾向性分析和意见挖掘,是指对带有情感色彩的主观性文本进行分析、处理、归纳和推理的过程。比如,从电影评论中分析用户对电影的喜恶,或者从商品评价中分析用户对商品的“价格”、“易用性”等属性的情感倾向。
情感分析还可以细分为情感极性(倾向)分析、情感程度分析及主客观分析等。其中,情感极性分析的目的在于,对文本进行褒义、贬义、中性的判断,比如对于“喜爱”和“厌恶”这两个词,就属于不同的情感倾向。
目前,常见的情感极性分析方法主要分为两种:基于情感词典和基于机器学习,有关它们的说明具体如下:
基于情感词典:主要通过制定一系列的情感词典和规则,对文本进行段落拆解、句法分析,计算情感值,最后通过情感值来作为文本的情感倾向依据。
基于机器学习:大多会把问题转换成分类问题来看待,是将目标情感分为两类:正、负,或者是根据不同的情感程度划分为1~5类,然后对训练文本进行人工标注,进行有监督的机器学习过程。
最简单的情感极性分析的方式就是情感词典,其实现的大致思路如下。
(1) 对文本进行分词操作,从中找出情感词、否定词以及程度副词。
(2) 判断每个情感词之前是否有否定词及程度副词,将它之前的否定词和程度副词划分为一组。如果存在否定词,则将情感词的情感权值乘以-1;如果有程度副词,就乘以程度副词的程度值。
(3) 将所有组的得分加起来,得分大于0的归于正向,小于0的归于负向。
例如,有这么一句商品评价:“这款蓝牙耳机的款式比较好看,操作也比较简单,不过音质真的太烂了,耳塞也不好用。”
按照上面的思路,就是要先找出这句话中的情感词。其中,积极的情感词有:“好看”、“简单”、“好用”,消极的情感词有“烂”,只要出现一个积极词就加1,出现一个消极词就减1。此时,这句话的情感分值为:1+1-1+1=2,这表明商品评价属于一条好评,很明显这个分值是不合理的。
接着,我们来看看这些情感词前面有没有程度词进行修饰,并且给不同的程度一个权值。比如,“太”表达的情感度更强,可以将情感分值设为4,“比较”这个词表达的程度没有前面的强,可以将它的情感分值设为2。此时,这句话的情感分值为:1*2+1*2-1*4+1=1
不过,在“好用”一词的前面还有一个“不”字,所以在找到情感词的时候,需要往前找否定词,还需要数一下这些否定词出现的次数。如果出现的是单数,则情感分数值就-1,如果是偶数,则情感分数值应该反转变为1。这句话中在“好用”的前面只有一个“不”字,所以其情感分值应该为*-1
。此时,这句话的情感分值为:1*2+1*2-1*4+1*-1=-1
,这表明商品评价属于一条差评。
使用情感词典的方式虽然简单粗暴,但是非常实用,不过一旦遇到一些新词或者特殊词,就无法识别出来,扩展性非常不好。
还可以基于机器学习模型进行情感极性分析,其中,朴素贝叶斯是经典的机器学习算法之一,也是为数不多的基于概率论的分类算法,它的思想基础是:对于给出的待分类项,求解在此项出现的条件下各个类别出现的概率,哪个最大,就认为此待分类项属于哪个类别。
nltk.classify模块中提供了用类别标签标记的接口,其内置的NaiveBayesClassifier类实现了朴素贝叶斯分类算法,该类中有一个类方法train(),其语法格式如下:
train (cls , labeled_featuresets , estimator = ELEProbDist)
上述方法主要用于根据训练集来训练模型,其中labeled_featuresets参数表示分类的特征集列表。
为了能够让读者更好地理解,接下来,通过一个简单示例来演示如何基于NaiveBayesClassifier类实现文本情感极性分析。假设,现在有如下一些有关评论的英文文本,每个所表达感情倾向的程度都不一样,具体代码如下。
In [23]: # 用作训练的文本
text_one = 'This is a wonderful book'
text_two = 'I like reading this book very much.'
text_thr = 'This book reads well.'
text_fou = 'This book is not good.'
text_fiv = 'This is a very bad book.'
接下来,导入专门用来预处理文本的模块,并且定义一个负责预处理文本的函数pret_text(),以便于处理多个测试文本,具体代码如下。
In [24]: import nltk
from nltk.stem import WordNetLemmatizer
from nltk.corpus import stopwords
from nltk.classify import NaiveBayesClassifier
def pret_text(text):
# 对文本进行分词
words = nltk.word_tokenize(text)
# 词形还原
wordnet_lematizer = WordNetLemmatizer()
words = [wordnet_lematizer.lemmatize(word) for word in words]
# 删除停用词
remain_words = [word for word in words if word not
in stopwords.words('english')]
# True 表示该词在文本中
return {word: True for word in remain_words}
上述函数中,先将文本按照空格划分为多个单词,然后将这些单词还原成基本形式,并根据英文的停用词表删除停用词,最后将剩下的单词以字典的形式进行返回,其中字典的键为单词,字典的值为True,代表着单词存在于预处理后的文本中。
然后,将上述待训练的文本经过预处理之后,为其设定情感分值,即将积极情感词的分值设为1,将消极情感词的分值设为-1,根据这些训练数据构建一个训练模型,具体代码如下。
In [25]: # 构建训练文本,设定情感分值
train_data = [[pret_text(text_one), 1],
[pret_text(text_two), 1],
[pret_text(text_thr), 1],
[pret_text(text_fou), -1],
[pret_text(text_fiv), -1]]
demo_model = NaiveBayesClassifier.train(train_data)
在训练文本中,前三个句子中都有表示积极情感的词汇,比如“wonderful”、“ like”、“well”,因此分值设为+1,而后三个句子里面包含了一些表示消极情感的词汇,比如“bad”、“ terrible”,因此设分值为-1。
根据这些训练文本构建了一个训练模型,意思是比如某个句子中出现了这个模型中的积极情感词汇,就将情感分值置为1,否则就把情感分值置为-1。
为了验证刚刚创建的情感模型是否可行,下面是一些测试的结果,具体代码如下。
In [26]: # 测试模型
test_text1 = 'I like this movie very much'
demo_model.classify(pret_text(test_text1))
Out[26]: 1
In [27]: test_text2 = 'The film is very bad'
demo_model.classify(pret_text(test_text2))
Out[27]: -1
In [28]: test_text3 = 'The film is terrible'
demo_model.classify(pret_text(test_text3))
Out[28]: 1
从输出的结果中可以看出,根据训练的模型已经能够准确地辨识出部分带有情感色彩的固定单词,比如,like、bad,一旦有新的情感单词出现,比如terrible,就无法辨识出来。