思路以及代码都来源于下面两篇文章:

一个不知死活的胖子:Python做文本情感分析之情感极性分析

Ran Fengzheng 的博客:基于情感词典的文本情感极性分析相关代码

基于情感词典的情感分析应该是最简单的情感分析方法了,大致说一下使用情感词典进行情感分析的思路:

对文档分词,找出文档中的情感词、否定词以及程度副词,然后判断每个情感词之前是否有否定词及程度副词,将它之前的否定词和程度副词划分为一个组,如果有否定词将情感词的情感权值乘以-1,如果有程度副词就乘以程度副词的程度值,最后所有组的得分加起来,大于0的归于正向,小于0的归于负向。

准备:

1.BosonNLP情感词典

既然是基于情感词典的分析,当然需要一份包含所有情感词的词典,网上已有现成的,直接下载即可。

https://bosonnlp.com/dev/resource

从下载的文件里,随便粘了几个正向的情感词,词后面的数字表示的是情感词的情感分值,一般正向的都是正数,负向的是负数:

丰富多彩 1.87317228434
神采飞扬 1.87321290817
细微 1.87336937803
178.00 1.87338705728
不辞辛劳 1.87338705728
保加利亚 1.87338705728

注:由于BosonNLP是基于微博、新闻、论坛等数据来源构建的情感词典,因此拿来对其他类别的文本进行分析效果可能不好

也有一种将所有情感词的情感分值设为1的方法来计算,想要详细了解可参考此文章:

文本情感分类(一):传统模型

2.否定词词典

文本情感分类(一):传统模型中提供了一个情感极性词典的下载包,包中带了一个否定词的txt。

不大
不丁点儿
不甚
不怎么
聊
没怎么
不可以
怎么不
几乎不
从来不
从不
不用
不曾
不该
不必
不会
不好
不能
很少
极少
没有
不是
难以
放下
扼杀
终止
停止
放弃
反对
缺乏
缺少
不
甭
勿
别
未
反
没
否
木有
非
无
请勿
无须
并非
毫无
决不
休想
永不
不要
未尝
未曾
毋
莫
从未
从未有过
尚未
一无
并未
尚无
从没
绝非
远非
切莫
绝不
毫不
禁止
忌
拒绝
杜绝
弗

3.程度副词词典

程度副词如:非常、很、特别...等词

原博中提供了《知网》情感分析用词语集(beta版)的下载链接,该词典中包含了程度副词已经对应的程度值,但是下载下来之后发现只有程度副词,并没有对应的程度值。

从程度级别词语.txt中选取了一部分程度副词,可以看到只有程度词,没有程度值,这个时候就自己看情况赋一个值好了:

中文程度级别词语     2191. “极其|extreme / 最|most” 69
百分之百
倍加
备至
不得了
不堪
不可开交
不亦乐乎
不折不扣
彻头彻尾
充分
到头
地地道道
非常
极
极度
极端
极其
极为
截然
尽
惊人地

改完之后的格式如下,程度副词和程度值用逗号分割,程度值可以自己定义:

百分之百,2
倍加,2
备至,2
不得了,2
不堪,2
不可开交,2
不亦乐乎,2
不折不扣,2
彻头彻尾,2
.....

4.停用词词典

数据堂的下载本地总是打不开,因此原博中提供的数据堂的中文停用词下载也是没下载下来,然后使用了snownlp源码中的停用词词典,但是后来发现有些情感词被当做停用词了

数据堂停用词下载:http://www.datatang.com/data/43894

snownlp源码:https://github.com/isnowfy/snownlp (停用词在snownlp/normal文件夹下 stopwords.txt)

5.分词工具

由于使用python,选择了jieba分词

数据和工具都准备好了,现在可以开始情感分析了~

来一个简单的句子:我今天很高兴也非常开心

(1)分词,去除停用词

我、今天、也被当作停用词去掉,剩下很、高兴、非常、开心

def seg_word(sentence):"""使用jieba对文档分词"""seg_list = jieba.cut(sentence)seg_result = []for w in seg_list:seg_result.append(w)# 读取停用词文件stopwords = set()fr = codecs.open('stopwords.txt', 'r', 'utf-8')for word in fr:stopwords.add(word.strip())fr.close()# 去除停用词return list(filter(lambda x: x not in stopwords, seg_result))

(2)将分词结果转为字典,key为单词,value为单词在分词结果中的索引,后来想到一个问题,如果把单词作为key的话假如一个情感词在文中出现了多次,那么应该是只记录了这个词最后一次出现的位置,其他的被覆盖掉了。

将上一步得到的分词结果转为字典:

{'很': 0, '高兴': 1, '非常': 2, '开心': 3}

def list_to_dict(word_list):"""将分词后的列表转为字典,key为单词,value为单词在列表中的索引,索引相当于词语在文档中出现的位置"""data = {}for x in range(0, len(word_list)):data[word_list[x]] = xreturn data

(3)对分词结果分类,找出情感词、否定词和程度副词

情感词sen_word(高兴和开心,key为单词的索引,value为情感权值):

{1: '1.48950851679', 3: '2.61234173173'}

程度副词degree_word(很和非常,key为索引,value为程度值)
{0: '1.75', 2: '2'}

否定词not_word,由于没有出现否定词,所以否定词为空:
{}

def classify_words(word_dict):"""词语分类,找出情感词、否定词、程度副词"""# 读取情感字典文件sen_file = open('BosonNLP_sentiment_score.txt', 'r+', encoding='utf-8')# 获取字典文件内容sen_list = sen_file.readlines()# 创建情感字典sen_dict = defaultdict()# 读取字典文件每一行内容,将其转换为字典对象,key为情感词,value为对应的分值for s in sen_list:# 每一行内容根据空格分割,索引0是情感词,索引1是情感分值(情感词典文件中有一行是空行,因此执行的时候会报错,注意处理一下空行,这里没有处理)sen_dict[s.split(' ')[0]] = s.split(' ')[1]# 读取否定词文件not_word_file = open('notDic.txt', 'r+', encoding='utf-8')# 由于否定词只有词,没有分值,使用list即可not_word_list = not_word_file.readlines()# 读取程度副词文件degree_file = open('degree.txt', 'r+', encoding='utf-8')degree_list = degree_file.readlines()degree_dic = defaultdict()# 程度副词与情感词处理方式一样,转为程度副词字典对象,key为程度副词,value为对应的程度值for d in degree_list:degree_dic[d.split(',')[0]] = d.split(',')[1]# 分类结果,词语的index作为key,词语的分值作为value,否定词分值设为-1sen_word = dict()not_word = dict()degree_word = dict()

(4)计算得分

首先设置初始权重W为1,从第一个情感词开始,用权重W*该情感词的情感值作为得分(用score记录),然后判断与下一个情感词之间是否有程度副词及否定词,如果有否定词将W*-1,如果有程度副词,W*程度副词的程度值,此时的W作为遍历下一个情感词的权重值,循环直到遍历完所有的情感词,每次遍历过程中的得分score加起来的总和就是这篇文档的情感得分。

def socre_sentiment(sen_word, not_word, degree_word, seg_result):"""计算得分"""# 权重初始化为1W = 1score = 0# 情感词下标初始化sentiment_index = -1# 情感词的位置下标集合sentiment_index_list = list(sen_word.keys())# 遍历分词结果(遍历分词结果是为了定位两个情感词之间的程度副词和否定词)for i in range(0, len(seg_result)):# 如果是情感词(根据下标是否在情感词分类结果中判断)if i in sen_word.keys():# 权重*情感词得分score += W * float(sen_word[i])# 情感词下标加1,获取下一个情感词的位置sentiment_index += 1if sentiment_index < len(sentiment_index_list) - 1:# 判断当前的情感词与下一个情感词之间是否有程度副词或否定词for j in range(sentiment_index_list[sentiment_index], sentiment_index_list[sentiment_index + 1]):# 更新权重,如果有否定词,取反if j in not_word.keys():W *= -1elif j in degree_word.keys():# 更新权重,如果有程度副词,分值乘以程度副词的程度分值W *= float(degree_word[j])# 定位到下一个情感词if sentiment_index < len(sentiment_index_list) - 1:i = sentiment_index_list[sentiment_index + 1]return score

W=1

score=0

第一个情感词是高兴,高兴的情感权值为1.48950851679,score=W*情感权值=1*1.48950851679=1.48950851679

高兴和下一个情感词开心之间出现了程度副词非常,程度值为2,因此W=W*2=1*2=2,然后获取下一个情感词

下一个情感词是开心,此时W=2,score=score+2*2.61234173173=1.48950851679+2*2.61234173173=6.71419198025

遍历结束

这里也发现两个问题:

(1)第一个情感词之前出现的程度副词和否定词被忽略了

(2)在判断两个情感词之间出现否定词以及程度副词时,W没有被初始化为1,这样W就被累乘了

有兴趣的可以修改一下~

完整代码:

from collections import defaultdict
import os
import re
import jieba
import codecsdef seg_word(sentence):"""使用jieba对文档分词"""seg_list = jieba.cut(sentence)seg_result = []for w in seg_list:seg_result.append(w)# 读取停用词文件stopwords = set()fr = codecs.open('stopwords.txt', 'r', 'utf-8')for word in fr:stopwords.add(word.strip())fr.close()# 去除停用词return list(filter(lambda x: x not in stopwords, seg_result))def classify_words(word_dict):"""词语分类,找出情感词、否定词、程度副词"""# 读取情感字典文件sen_file = open('BosonNLP_sentiment_score.txt', 'r+', encoding='utf-8')# 获取字典文件内容sen_list = sen_file.readlines()# 创建情感字典sen_dict = defaultdict()# 读取字典文件每一行内容,将其转换为字典对象,key为情感词,value为对应的分值for s in sen_list:# 每一行内容根据空格分割,索引0是情感词,索引01是情感分值sen_dict[s.split(' ')[0]] = s.split(' ')[1]# 读取否定词文件not_word_file = open('notDic.txt', 'r+', encoding='utf-8')# 由于否定词只有词,没有分值,使用list即可not_word_list = not_word_file.readlines()# 读取程度副词文件degree_file = open('degree.txt', 'r+', encoding='utf-8')degree_list = degree_file.readlines()degree_dic = defaultdict()# 程度副词与情感词处理方式一样,转为程度副词字典对象,key为程度副词,value为对应的程度值for d in degree_list:degree_dic[d.split(',')[0]] = d.split(',')[1]# 分类结果,词语的index作为key,词语的分值作为value,否定词分值设为-1sen_word = dict()not_word = dict()degree_word = dict()# 分类for word in word_dict.keys():if word in sen_dict.keys() and word not in not_word_list and word not in degree_dic.keys():# 找出分词结果中在情感字典中的词sen_word[word_dict[word]] = sen_dict[word]elif word in not_word_list and word not in degree_dic.keys():# 分词结果中在否定词列表中的词not_word[word_dict[word]] = -1elif word in degree_dic.keys():# 分词结果中在程度副词中的词degree_word[word_dict[word]] = degree_dic[word]sen_file.close()degree_file.close()not_word_file.close()# 将分类结果返回return sen_word, not_word, degree_worddef list_to_dict(word_list):"""将分词后的列表转为字典,key为单词,value为单词在列表中的索引,索引相当于词语在文档中出现的位置"""data = {}for x in range(0, len(word_list)):data[word_list[x]] = xreturn datadef get_init_weight(sen_word, not_word, degree_word):# 权重初始化为1W = 1# 将情感字典的key转为listsen_word_index_list = list(sen_word.keys())if len(sen_word_index_list) == 0:return W# 获取第一个情感词的下标,遍历从0到此位置之间的所有词,找出程度词和否定词for i in range(0, sen_word_index_list[0]):if i in not_word.keys():W *= -1elif i in degree_word.keys():# 更新权重,如果有程度副词,分值乘以程度副词的程度分值W *= float(degree_word[i])return Wdef socre_sentiment(sen_word, not_word, degree_word, seg_result):"""计算得分"""# 权重初始化为1W = 1score = 0# 情感词下标初始化sentiment_index = -1# 情感词的位置下标集合sentiment_index_list = list(sen_word.keys())# 遍历分词结果(遍历分词结果是为了定位两个情感词之间的程度副词和否定词)for i in range(0, len(seg_result)):# 如果是情感词(根据下标是否在情感词分类结果中判断)if i in sen_word.keys():# 权重*情感词得分score += W * float(sen_word[i])# 情感词下标加1,获取下一个情感词的位置sentiment_index += 1if sentiment_index < len(sentiment_index_list) - 1:# 判断当前的情感词与下一个情感词之间是否有程度副词或否定词for j in range(sentiment_index_list[sentiment_index], sentiment_index_list[sentiment_index + 1]):# 更新权重,如果有否定词,取反if j in not_word.keys():W *= -1elif j in degree_word.keys():# 更新权重,如果有程度副词,分值乘以程度副词的程度分值W *= float(degree_word[j])# 定位到下一个情感词if sentiment_index < len(sentiment_index_list) - 1:i = sentiment_index_list[sentiment_index + 1]return score# 计算得分
def setiment_score(sententce):# 1.对文档分词seg_list = seg_word(sententce)# 2.将分词结果列表转为dic,然后找出情感词、否定词、程度副词sen_word, not_word, degree_word = classify_words(list_to_dict(seg_list))# 3.计算得分score = socre_sentiment(sen_word, not_word, degree_word, seg_list)return score# 测试
print(setiment_score("我今天很高兴也非常开心"))

基于情感词典的情感分析相关推荐

  1. [Python人工智能] 二十二.基于大连理工情感词典的情感分析和情绪计算

    从本专栏开始,作者正式研究Python深度学习.神经网络及人工智能相关知识.前一篇文章分享了CNN实现中文文本分类的过程,并与贝叶斯.决策树.逻辑回归.随机森林.KNN.SVM等分类算法进行对比.这篇 ...

  2. 基于NRC词典的情感分析(含多种离散情绪)——python

    NRC词典简介: NRC词典由加拿大国家研究委员会(简称NRC)的专家创建,目前已有多种语言版本,我们可以用其中文版本来进行情感分析.使用一系列单词来帮助识别情绪,情感,并分析标签,表情符号和单词颜色 ...

  3. python 基于情感词典的情感分析之乐,惧,惊,哀,恶,怒和未知七种情感分析

    背景 情感分析是通过计算技术对文本内容的主观客观性.情绪等挖掘分析,对文本的情感偏向做出判断.目的是识别出文本中的具体情感分类,之前做文本分类都是通过深度学习或者机器学习进行文本分类,但是需要进行数据 ...

  4. python情感词典计算得分_基于情感词典的情感打分

    原理我就不讲了,请移步下面这篇论文,包括情感词典的构建(各位读者可以根据自己的需求稍作简化),以及打分策略(程序对原论文稍有改动). 论文在这里下载:基于情感词典的中文微博情感倾向性研究 (大家可以上 ...

  5. 基于情感词典的情感打分

    原理我就不讲了,请移步下面这篇论文,包括情感词典的构建(各位读者可以根据自己的需求稍作简化),以及打分策略(程序对原论文稍有改动). 论文在这里下载:基于情感词典的中文微博情感倾向性研究  (大家可以 ...

  6. 基于情感词典的情感值分析

    #utils.py import reclass ToolGeneral():"""Tool function"""def is_odd(s ...

  7. 实体词典 情感词典_基于词典的情感分析——简单实例

    基于词典的情感分析方法非常容易被理解,主要利用情感词判断一句话或者一篇文章的情感倾向,下面的程序利用BosonNLP情感词典(从https://bosonnlp.com/dev/resource 下载 ...

  8. 情感极性分析:基于情感词典、k-NN、Bayes、最大熵、SVM的情感极性分析

    向AI转型的程序员都关注了这个号???????????? 机器学习AI算法工程   公众号:datayx 1.预处理 (1).特征提取 对应文件:feature_extraction.py 最后结果: ...

  9. 基于情感词典的python情感分析!它居然比我还懂我女友!

    近期老师给我们安排了一个大作业,要求根据情感词典对微博语料进行情感分析.于是在网上狂找资料,看相关书籍,终于搞出了这个任务.现在做做笔记,总结一下本次的任务,同时也给遇到有同样需求的人,提供一点帮助. ...

最新文章

  1. Linux文件系统映像:Initranfs 和 Initrd
  2. 成功解决ValueError: Parameter values for parameter (max_depth) need to be a sequence.
  3. 不安全的食品,如何“安全地”上了货架?
  4. 高等专科学校计算机,理工类计算机专业较好的高等专科学校
  5. centos主题设置
  6. 从键盘输入一个正整数(不多于5位),计算该正整数与789之和(记为sum)
  7. oracle语句取字段前2位,oracle截取某一个字符之前或之后的值;substr();instr()
  8. TC SRM601
  9. [转]删除表中重复记录
  10. C++中对多态的理解
  11. android 获取GPS定位,
  12. 使用VS2015编译OpenJDK8
  13. java map size 不准确_java1.7以前ConcurrentHashMap的size方法
  14. java源码反编译_Java代码的编译与反编译
  15. fritzing元件太少_fritzing传感器元件库
  16. 计算机生存代码,方舟生存进化OL代码大全 最新最全的代码
  17. Linux下使用服务器24小时不间断直播电影电视剧
  18. 从数学归纳法到递归算法
  19. 人生需要执著——从二本三战到985博士
  20. Docker系列之常用命令操作手册

热门文章

  1. debian e42 wifi
  2. 如何用vnc远程到服务器,如何利用VNC远程控制Linux
  3. 域名备案批量在线查询 如何批量查询域名备案情况?
  4. american主板网卡灯关机后还亮_安装黑苹果出问题,安装到最后一分钟黑屏,硬盘灯灭了后重启进苹果系统卡死,有图。...
  5. 科普:ERP与EDI是一回事吗?
  6. bootmgr is conmpressed联想Z485
  7. 使用JS代码禁止某些地区用户访问网站
  8. Win10电脑提示Task Host Window阻止关机解决方法
  9. 【180720】坦克大战电脑版小游戏源码
  10. 0c400汇编语言地址,在S7300/400型PLC中使用高级语言编程实例