一、引言
目前中文文本情感分析主要分为三个类型,第一个是由情感词典和句法结构来做的、第二个是根据机器学习来做的(Bayes、SVM等)、第三个是用深度学习的方法来做的(例如LSTM、CNN、LSTM+CNN、BERT+CNN等)。
这三种方法中,第二种和第三种方法都需要人工标注大量的数据,然后做有监督的训练。只有第一种不需要人工标注,也不需要训练。
接下来,我们会介绍下第一种方法的算法逻辑,以及如何实践。
二、情感字典
除了分词词典和停用词词典外,一共还包含9个词典:
1、否定词:not.txt
2、正面情感词:positive.txt
3、负面情感词:negative.txt
4、程度副词:most.txt
very.txt
more.txt
ish.txt
insufficiently.txt
over.txt
inverse.txt
三、算法流程设计算法逻辑Step 1:读取评论数据,对评论进行分句(分句主要以特定的标点符号为主)。
Step 2:将结巴词典和所有情感词典做并集,得出新的分词词典。
Step 3:查找分句的情感词,记录正面还是负面,以及位置。
Step 4:在情感词前查找程度词,找到就停止搜寻。为程度词设权值,乘以情感值。
Step 5:在情感词前查找否定词,找完全部否定词,若数量为奇数,乘以-1,若为偶数, 乘以 1。
Step 6:找出感叹号和问好等重要的标点符合
- 判断分句结尾是否有感叹号,有叹号则往前寻找情感词,有则相应的情感值+2。
- 判断分句结尾是否有问好,有问号该句判断为负面值+2。
Step 7:计算完一条评论所有分句的情感值([正面分值, 负面分值]),用数组(list) 记录起来。
Step 8:计算每条评论中每一个分句的的正面情感均值与负面情感均值,然后比较正面情感总和与负面情感总和,较大的一个即为所得情感倾向。
2. 代码演示
class SentimentAnalysis():
"""Sentiment Analysis with some dictionarys"""
def sentiment_score_list(self,dataset):
seg_sentence = tool.sentence_split_regex(dataset)
count1,count2 = [],[]
for sentence in seg_sentence:
words = jieba.lcut(sentence, cut_all=False)
i = 0
a = 0
for word in words:
"""poscount 积极词的第一次分值;poscount2 积极反转后的分值;poscount3 积极词的最后分值(包括叹号的分值)"""
poscount,negcount,poscount2,negcount2,poscount3,negcount3 = 0,0,0,0,0,0 #
if word in hp.posdict :
if word in ['好','真','实在'] and words[min(i+1,len(words)-1)] in hp.pos_neg_dict and words[min(i+1,len(words)-1)] != word:
continue
else:
poscount +=1
c = 0
for w in words[a:i]: # 扫描情感词前的程度词
if w in hp.mostdict:
poscount *= 4
elif w in hp.verydict:
poscount *= 3
elif w in hp.moredict:
poscount *= 2
elif w in hp.ishdict:
poscount *= 0.5
elif w in hp.insufficientlydict:
poscount *= -0.3
elif w in hp.overdict:
poscount *= -0.5
elif w in hp.inversedict:
c+= 1
else:
poscount *= 1
if tool.is_odd(c) == 'odd': # 扫描情感词前的否定词数
poscount *= -1.0
poscount2 += poscount
poscount = 0
poscount3 = poscount + poscount2 + poscount3
poscount2 = 0
else:
poscount3 = poscount + poscount2 + poscount3
poscount = 0
a = i+1
elif word in hp.negdict: # 消极情感的分析,与上面一致
if word in ['好','真','实在'] and words[min(i+1,len(words)-1)] in hp.pos_neg_dict and words[min(i+1,len(words)-1)] != word:
continue
else:
negcount += 1
d = 0
for w in words[a:i]:
if w in hp.mostdict:
negcount *= 4
elif w in hp.verydict:
negcount *= 3
elif w in hp.moredict:
negcount *= 2
elif w in hp.ishdict:
negcount *= 0.5
elif w in hp.insufficientlydict:
negcount *= -0.3
elif w in hp.overdict:
negcount *= -0.5
elif w in hp.inversedict:
d += 1
else:
negcount *= 1
if tool.is_odd(d) == 'odd':
negcount *= -1.0
negcount2 += negcount
negcount = 0
negcount3 = negcount + negcount2 + negcount3
negcount2 = 0
else:
negcount3 = negcount + negcount2 + negcount3
negcount = 0
a = i + 1
i += 1
pos_count = poscount3
neg_count = negcount3
count1.append([pos_count,neg_count])
if words[-1] in ['!','!']:# 扫描感叹号前的情感词,发现后权值*2
count1 = [[j*2 for j in c] for c in count1]
for w_im in ['但是','但']:
if w_im in words : # 扫描但是后面的情感词,发现后权值*5
ind = words.index(w_im)
count1_head = count1[:ind]
count1_tail = count1[ind:]
count1_tail_new = [[j*5 for j in c] for c in count1_tail]
count1 = []
count1.extend(count1_head)
count1.extend(count1_tail_new)
break
if words[-1] in ['?','?']:# 扫描是否有问好,发现后为负面
count1 = [[0,2]]
count2.append(count1)
count1=[]
return count2
四、举例分析
例子:“我特别喜欢武汉这个城市!因为武汉有非常多好看的景点。但是,我不喜欢武汉的天气,因为武汉的天气有点差,热的时候让人感觉不爽。”
1、 情感词分为 2 种, 一种是正面的,另外一种是负面的。
要分析一句话是正面的还是负面的,首先需要找出句子里面的情感词,然后再找出程度副词和否定词等。
正面的情感词比如:好,孝顺,高性能,一心一意等。 负面情感词比如:差,郁闷,小心眼,一毛不拔等。 出现一个积极词就+1,出现一个消极词就-1。 在这句话里面,有“好看”和“喜欢”两个正面情感词,“差”和“不爽”两个负面情感词。
2、 情感词 “喜欢”、“好看”和‘差“前面都有一个程度副词。”极好“就比”较好“和”好“的情感更强烈,”太差“也比”有点差“情感强一些。 所以需要在找到情感词后往前找一下有没有程度副词,**在这里不同的程度副词有不同的权重**。 程度词我们分为 6 种,分别为:most,very,more,ish,insufficient 和 over 通过测试计算,给上面 6 种情感词的打分分别为 4,3,2,0.5,-0.3 和-0.5。
3、”我特别喜欢武汉这个城市“后面有感叹号,叹号意味着情感强烈。因此发现叹号可以为情 感值+2.
4、 否定词 在找到情感词的时候,需要往前找否定词。比如”不“,”不能“这些词。而且还要数这些否 定词出现的次数,如果是单数,情感分值就*-1,但如果是偶数,那情感就没有反转,还 是1。在这句话里面,可以看出”喜欢“前面只有一个”不“,所以”喜欢“的情感值应该反 转,-1。
5、 正面和负面需要分别独立计算,很明显就可以看出,这句话里面有褒有贬,不能用一个分值来表示它的情感倾 向。而且这个权值的设置也会影响最终的情感分值,敏感度太高了。因此对这句话的最终的正确的处理,是得出这句话的一个正面分值,一个负面分值(这样消极分值也是正数, 无需使用负数了)。
6、 以分句的情感为基础,加权求和,从而得到一条评论的情感分值。
这条例子评论有五个分句, 因此其结构如下([正面分值, 负面分值]): 下面是对每个分句的打分: [正面分值, 负面分值]
① 我 特别 喜欢 武汉这个城市 ! [正面分值, 负面分值] : [3*1+2,0]
② 因为武汉有 非常 多 好看 的景点。 [正面分值, 负面分值] : [4*1,0]
③ 但是, [正面分值, 负面分值] : [0,0]
④ 我 不 喜欢 武汉的天气, [正面分值, 负面分值] : [-1*1,0]
⑤ 因为武汉的天气 有点 差, [正面分值, 负面分值] : [0,0.5*1]
⑥ 热的时候让人感觉 不爽。 [正面分值, 负面分值] : [0,1]
最后,这句话的得分为: [3*1+2,0] + [4*1,0] + [0,0] + [-1*1,0] + [0,0.5*1] + [0,1] = [8,1.5],即为: [正面分值, 负面分值] = [8,1.5]。
因为 8>1.5,所以整句话的情感判断为正面。
五、总结
如果我们仅仅使用情感词典的方法,准确率可以达到 73%左右。这种比较通用,不需要训练,对于不同类型的数据都可以进行情感分析。唯一的缺点就是准确率不是非常高。
六、Github代码链接:hellonlp/sentiment_analysis_dict
***** 欢迎大家的小星星 *****
七、HelloNLP网站:HelloNLP|哈罗中文语义|自然语言处理