基于python的情感分析案例_约翰肯尼格的悲伤词典

基于python的情感分析案例_约翰肯尼格的悲伤词典情感分析是大数据时代常见的一种分析方法,多用于对产品评论的情感挖掘,以探究顾客的满意度程度。在做情感分析时,有两种途径:一种是基于情感词典的分析方法,一种是基于机器学习的方法,两者各有利弊。在此,笔者主要想跟大家分享基于python平台利用情感词典做情感分析的方法。本文主要参考https://blog.csdn.net/lom9357bye/article/details/79058946这篇文章,在此文章中,博主用一句简单的语句“我今天很高兴也非常开心”向我们清楚的展示的利用情感词典做情感分析的方法,这

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

情感分析是大数据时代常见的一种分析方法,多用于对产品评论的情感挖掘,以探究顾客的满意度程度。在做情感分析时,有两种途径:一种是基于情感词典的分析方法,一种是基于机器学习的方法,两者各有利弊。
在此,笔者主要想跟大家分享基于python平台利用情感词典做情感分析的方法。本文主要参考https://blog.csdn.net/lom9357bye/article/details/79058946这篇文章,在此文章中,博主用一句简单的语句“我今天很高兴也非常开心”向我们清楚的展示的利用情感词典做情感分析的方法,这篇文章对笔者很受用。
然而这篇文章博主也向我们抛出了几个问题,笔者就是基于此改写的算法。主要分以下几个步骤:
(1)过滤掉停用词表中的否定词和程度副词
有时候,停用词表中的词包括了否定词和程度副词,因此在做情感分析时首要先过滤掉停用词表中的否定词和程度副词,防止这些有意义的词被过滤掉。词表的下载见上述博主。

"""在停用词表中过滤否定词和程度副词"""
#生成stopword表,需要去除一些否定词和程度词汇
stopwords = set()
fr = open('stopwords.txt','r',encoding='utf-8')
for word in fr:
    stopwords.add(word.strip())#Python strip() 方法用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列。
    # #读取否定词文件
    not_word_file = open('否定词.txt','r+',encoding='utf-8')
    not_word_list = not_word_file.readlines()
    not_word_list = [w.strip() for w in not_word_list]
    #读取程度副词文件
    degree_file = open('程度副词.txt','r+')
    degree_list = degree_file.readlines()
    degree_list = [item.split(',')[0] for item in degree_list]
    #生成新的停用词表
    with open('stopwords_new.txt','w',encoding='utf-8') as f:
        for word in stopwords:
            if(word not in not_word_list) and (word not in degree_list):
                f.write(word+'\n')

(2)分词,过滤停用词

def seg_word(sentence):
    jieba.load_userdict("./dict.txt")
    seg_list = jieba.cut(sentence)
    seg_result = []
    # 读取停用词文件
    stopwords = [line.strip() for line in open('stopwords_new.txt', encoding='UTF-8').readlines()]
    # 去停用词
    for word in seg_list:  # 读取每一行分词
        if word not in stopwords:  # 如果分词不在停用词列表中
            if word != '\t':
                seg_result.append(word)
    print(seg_result)
    return seg_result

(3)找出分词结果中的情感词、否定词和程度副词
在博主的文章中,这里出现了一个错误就是如果句子中出现两个相同的情感词、程度副词和否定词的话,前面的就会被后面的覆盖掉了,这是因为博主将分词结果转换成了以词作为key,索引作为value的字典形式,但如果我们只对分词结果以列表的形式进行遍历,则可避免这种情况的发生。

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

(4)计算情感值
在计算情感值的过程中,博主提出了两个问题,第一是对第一个情感词之前的程度副词和否定词的判断情况,第二个就是权重W没有初始化,被累乘的情况。笔者将它改成下面的代码形式,完美解决了这两个问题。

#1.用来判断第一个情感词之前的程度副词和否定词
def get_init_weight(sen_word, not_word, degree_word):
    # 权重初始化为1
    W = 1
    # 将情感字典的key转为list
    sen_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 *= -1
        elif i in degree_word.keys():
            #更新权重,如果有程度副词,分值乘以程度副词的程度分值
            W *= float(degree_word[i])
    return W
    #2.计算得分
def socre_sentiment(sen_word, not_word, degree_word, seg_result):
    W = get_init_weight(sen_word, not_word, degree_word)
    print(W)
    score = 0
    # 情感词下标初始化
    sentiment_index = -1
    # 情感词的位置下标集合
    sentiment_index_list = list(sen_word.keys())
    #print(sentiment_index_list)
    # 遍历分词结果(遍历分词结果是为了定位两个情感词之间的程度副词和否定词)
    for i in range(0, len(seg_result)):
        # 如果是情感词(根据下标是否在情感词分类结果中判断)
        if i in sen_word.keys():
            # 权重*情感词得分
            score += W * float(sen_word[i])
            print(score)
            # 情感词下标加1,获取下一个情感词的位置
            sentiment_index += 1
            print("sentiment_index:",sentiment_index)
            if sentiment_index < len(sentiment_index_list) - 1:  #总的情感词的个数
                # 判断当前的情感词与下一个情感词之间是否有程度副词或否定词
                """这个是解决W累乘情况的"""
                W=1  #防止第二轮的权重出现累乘的情况
                for j in range(sentiment_index_list[sentiment_index], sentiment_index_list[sentiment_index + 1]):
                    # 更新权重,如果有否定词,取反
                    if j in not_word.keys():
                        W *= -1
                    elif j in degree_word.keys():
                        # 更新权重,如果有程度副词,分值乘以程度副词的程度分值
                        W *= float(degree_word[j])
                    print(W)
                    """这里又出现了一个问题,就是后一个没有否定词和程度副词的权重会将前一个覆盖掉,所以初始化权重W=1不能放在for循环中"""
        # 定位到下一个情感词
        if sentiment_index < len(sentiment_index_list) - 1:
            i = sentiment_index_list[sentiment_index + 1]
    return score

(5)测试
测试过程中,笔者用了一句和博主测试语句情感相反的语句,“我很不高兴也非常不开心”

seg_list = seg_word("我很不高兴也非常不开心")  
sen_word, not_word, degree_word = classify_words(seg_list)
score = socre_sentiment(sen_word, not_word, degree_word, seg_list)
print(score)

测试结果如下图所示:在这里插入图片描述
其中,第一行表示的是分词结果,第二行表示的是分词结果中情感词、否定词和程度副词词典
第三行表示的就是第一个情感词之前的否定词和程度副词所代表的权重,其中“很”的权重是1.6,“不”的权重是-1,那么第一次循环中的得分score=(-1)1.6score(“高兴”),第二次循环求得的是第一个情感词“高兴”和第二个情感词“开心”之间的权重,也就是“非常”=1.8,”不“=-1,第二次求得的分数score=上一次循环中求得的分值+(-1)1.8score(”开心“)。由于没有下一个情感词了,所以这也是最终句子的情感值得分。

参考来源:https://blog.csdn.net/lom9357bye/article/details/79058946

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/172443.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 网页内容变化实时监控提醒(多个复杂的监控条件)

    网页内容变化实时监控提醒(多个复杂的监控条件)网页内容更新后,如果更新的内容满足一个或多个条件时,就发出报警提醒。1、如下图所示,地震台网站实时显示地震信息,如果发生新的地震且震级大于等于5.0级、震源深度小于50千米时报警提醒。先观察一下页面布局,最新的地震信息永远显示在第一行,因此我们也只需要监控第一行地震数据更新就可以了。首先,点击木头浏览器自动控制菜单下的项目管理器。2、在木头浏览器项目管理窗口左侧的步骤树中点击右键,新建一个定时控制步骤,并设定间隔30秒执行一次。3、新建一个打开网页的步骤,输入地震台网站地址4、新建一个元素

    2022年7月17日
    11
  • 程序猿的三高:高并发、高性能、高可用

    程序猿的三高:高并发、高性能、高可用

    2021年10月3日
    49
  • 计算机网络双绞线和交叉线的区别,交叉线-什么是交叉线、直通线和双绞线?各有什么区别 – 手机爱问…「建议收藏」

    计算机网络双绞线和交叉线的区别,交叉线-什么是交叉线、直通线和双绞线?各有什么区别 – 手机爱问…「建议收藏」2018-11-08简述制作双绞线两种标准的线排序和直通线网线由一定距离长的双绞线与RJ45头组成。双绞线由8根不同颜色的线分成4对绞合在一起,成队扭绞的作用是尽可能减少电磁辐射与外部电磁干扰的影响,双绞线可按其是否外加金属网丝套的屏蔽层而区分为屏蔽双绞线(STP)和非屏蔽双绞线(UTP)。在EIA/TIA-568A标准中,将双绞线按电气特性区分有:三类、四类、五类线。网络中最常用的是三类线和…

    2022年6月19日
    27
  • kworker进程_线程池队列类型

    kworker进程_线程池队列类型工作队列是另一种将工作推后执行的形式,它可以把工作交给一个内核线程去执行,这个下半部是在进程上下文中执行的,因此,它可以重新调度还有睡眠。    区分使用软中断/tasklet还是工作队列比较简单,如果推后的工作不需要睡眠,那么就选择软中断或tasklet,但如果需要一个可以重新调度,可以睡眠,可以获取内存,可以获取信号量,可以执行阻塞式I/O操作时,那么,请选择工作队列吧!    在老的

    2022年9月24日
    1
  • lofter限流怎么解决_高并发限流

    lofter限流怎么解决_高并发限流前言:学习本篇博客是有一些前提基础的1、熟悉gateway网关使用2、熟悉nginx使用3、熟悉sentinel的应用,会涉及网关规则持久化改造看不懂的童鞋们可以补一下微服务gateway网关和Sentinel相关知识秒杀链路兜底方案之限流&降级实战一、秒杀场景介绍1.1秒杀场景的特点1.2流量消峰1.3兜底方案二、限流实战2.1nginx限流(https://nginx.org/en/docs)2.2网关限流2.2.1网关接入sentinel控制台2.2.2Sentinel

    2022年10月6日
    0

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号