前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >中文情感词库_情感识别

中文情感词库_情感识别

作者头像
全栈程序员站长
发布2022-09-23 10:32:36
1.3K0
发布2022-09-23 10:32:36
举报
文章被收录于专栏:全栈程序员必看

大家好,又见面了,我是你们的朋友全栈君。


前言

文本情感倾向性分析(也称为意见挖掘)是指识别和提取原素材中的主观信息,并对带有感情色彩的文本进行分析处理和归纳推理的过程。主要用于实时社交媒体的内容,如微博评论等。而BosonNLP情感词典是从微博、新闻、论坛等数据来源的上百万篇情感标注数据当中自动构建的情感极性词典。因为标注包括微博等网络社交媒体平台的数据,该词典囊括了很多网络用语及非正式简称,对非规范文本也有较高的覆盖率。本文主要基于BosonNLP情感词典,同时使用程度副词词典和否定词词典(借助《知网》情感分析用词语集等文本构建)和哈工大停用词表,共同通过情感打分的方式进行(这里以前文《利用Python系统性爬取微博评论》https://blog.csdn.net/kutalx/article/details/115242052)中获取的评论数据为依托)的情感倾向性分析。


提示:代码实现部分参考了文章Python做文本情感分析之情感极性分析的内容,并在其基础上进行了优化,以适配个人需求。

一、模型构建

1.归类

采用的手段为遍历匹配相应的词性词典并对每条评论建立对应的位置词典。分词后文本内的所有词语彼此独立,故对于每一条评论,将其内部的每一个词分别归类于“情感词”、“否定词”、“程度词”和“其它词”四类中。具体步骤为先读取情感词典、否定词词典和程度副词词典,转化为“词语-分值”映射关系;再读取一条分词后评论,新建三个位置词典,内含“位置-分值”映射关系,依次对每个词进行分类,将每个词的位置录入对应的位置词典中。

2.判定

采用的手段为遍历每条评论的位置信息,输出情感分数。一条评论的初始分数为0;按位置遍历内部词语,若一个词被判定为“情感词”,则按照情感位置词典读取分数;若两个“情感词”之间有词语被判定为“否定词”或“程度词”,则按照否定位置词典或程度位置词典读取分数(“否定词”实则皆为-1),将之与后一个“情感词”分数相乘;最后将一条评论的所有情感词分数相加,得其总分数。算式如下: S w = ( − 1 ) N n ∗ ∑ i = 1 N d D s ∗ S o S_w=(-1)^{N_n}*\sum_{i=1}^{N_d} D_s*S_o Sw​=(−1)Nn​∗i=1∑Nd​​Ds​∗So​ S s = ∑ i = 1 N o S o S_s=\sum_{i=1}^{N_o} S_o Ss​=i=1∑No​​So​ 其中, S w S_w Sw​为单一情感词的最终分数, N n N_n Nn​、 N o N_o No​为前缀否定词和程度词的数 D s D_s Ds​、 S o S_o So​为前缀每个程度词的分数和单一情感词的原始分数; S s S_s Ss​为一票评论的最终分数, N o N_o No​为该评论类情感词的个数。

3.输出

每部作品有多条评论,每条评论的分值分布是离散的。将评论分值划分为五个等级:5(正面),4(偏正面),3(中性),2(偏负面),1(负面)。根据分值的分布特征,算式如下: D e g r e e = { 5 S s ≥ 3 4 0.5 ≤ S s < 3 3 − 0.5 < S s < 0.5 2 − 3 < S s ≤ − 0.5 1 S s ≤ − 3 Degree=\left\{ \begin{array}{rcl} 5 & & {S_s≥3}\\ 4 & & {0.5≤S_s<3}\\ 3 & & {-0.5<S_s<0.5}\\ 2 & & {-3<S_s≤-0.5}\\ 1 & & {S_s≤-3} \end{array} \right. Degree=⎩⎪⎪⎪⎪⎨⎪⎪⎪⎪⎧​54321​​Ss​≥30.5≤Ss​<3−0.5<Ss​<0.5−3<Ss​≤−0.5Ss​≤−3​ 由此即可得整体情感倾向水平。

情感分析流程图
情感分析流程图

流程如上;其中,“文件5”为评论文本文档,以微博id命名方便后续对应读取。

二、代码实现

使用python实现模型,代码如下:

代码语言:javascript
复制
from collections import defaultdict
import os
import re
import jieba
import codecs
def classifyWords(wordDict):
    senList = open(存储路径-情感词典).readlines()
    senDict = defaultdict()
    for s in senList:
        ls=s.split(' ',1)
        if len(ls)==2:
            senDict[ls[0]] = ls[1]
    notList = open(存储路径-否定词典).readlines()
    degreeList = open(存储路径-程度词典).readlines()
    degreeDict = defaultdict()
    for d in degreeList:
        ls2 = d.split(',', 1)
        if len(ls2) == 2:
            degreeDict[ls2[0]] = ls2[1]
    senWord = defaultdict()
    notWord = defaultdict()
    degreeWord = defaultdict()
    for word in wordDict.keys():
        if word in senDict.keys() and word not in notList and word not in degreeDict.keys():
            senWord[wordDict[word]] = senDict[word]
        elif word in notList and word not in degreeDict.keys():
            notWord[wordDict[word]] = -1
        elif word in degreeDict.keys():
            degreeWord[wordDict[word]] = degreeDict[word]
    return senWord, notWord, degreeWord
def scoreSent(senWord, notWord, degreeWord, segResult):
    W = 1
    score = 0
    senLoc = senWord.keys()
    notLoc = notWord.keys()
    degreeLoc = degreeWord.keys()
    senloc = -1
    for i in range(0, len(segResult)):
        if i in senLoc:
            senloc += 1
            score += W * float(senWord[i])
            if senloc < len(senLoc) - 1:
                for j in range(list(senLoc)[senloc], list(senLoc)[senloc + 1]):
                    if j in notLoc:
                        W *= -1
                    if j in degreeLoc:
                        W *= float(list(degreeWord)[j])
        if senloc < len(senLoc) - 1:
            i = list(senLoc)[senloc + 1]
    return score
uid=#微博id列表
for n in uid:#多个微博的评论文本分别评分
    txt = open(存储路径-文件5).readlines()
    stop = open(存储路径-停用词表).readline()
    line=[]
    for i in range(len(txt)):
        line.append(list(jieba.cut(txt[i])))
    ScoreList=[]
    for i in range(len(line)):
        words=line[i]
        num=list(range(0,len(words)))
        d=dict(zip(words,num))
        s,no,d=classifyWords(d)
        Score=scoreSent(s, no, d, words)
        ScoreList.append(Score)
    VBIG=0
    BIG=0
    SMALL=0
    VSMALL=0
    MID=0
    for score in ScoreList:
        if score>=3:
            VBIG=VBIG+1
        elif score>=0.5:
            BIG=BIG+1
        elif score>=-0.5:
            MID=MID+1
        elif score>-3:
            SMALL=SMALL+1
        else:
            VSMALL=VSMALL+1
    print(VBIG,BIG,MID,SMALL,VSMALL)
    print("---")

三、结果展示

六部作品评论的情感倾向水平
六部作品评论的情感倾向水平

分别选取《山海情》《大江大河2》《巡回检察组》《金刚川》《我和我的祖国》《中国机长》六部作品对应的官方微博下的所有评论,使用上述模型进行分析,结果如上。 在《山海情》19996条评论中,“正面”、“偏正面”、“中性”、“偏负面”、“负面”评论对应的数目分别为7268条,5771条,3042条2946条和969条;在《大江大河2》48264条评论中,分别有24289条,10445条,5518条5582条和2430条;在《巡回检察组》20090条评论中,分别有4577条,5173条,3751条,4356条和2233条;在《金刚川》7296条评论中,分别有4016条,1600条,714条700条和266条;在《我和我的祖国》38053条中,分别有24772条,6855条,3039条2579条和808条;在《中国机长》16900条中,分别有7747条,4231条,2343条1951条和628条。 可以看出,每部作品的正面评价往往略多于或远多于消极评价,符合实际网络评论的情况;而《巡回检察组》相对而言具有最差的口碑,这也符合客观观看评价的情况。

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

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 一、模型构建
    • 1.归类
      • 2.判定
        • 3.输出
        • 二、代码实现
        • 三、结果展示
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档