基于词典的中文情感倾向分析算法设计
![]() |
情感倾向可认为是主体对某一客体主观存在的内心喜恶,内在评价的一种倾向。它由两个方面来衡量:一个情感倾向方向,一个是情感倾向度。
情感倾向方向也称为情感极性。在微博中,可以理解为用户对某客体表达自身观点所持的态度是支持、反对、中立,即通常所指的正面情感、负面情感、中性情感。例如“赞美”与“表扬”同为褒义词,表达正面情感,而“龌龊”与“丑陋”就是贬义词,表达负面情感。
情感倾向度是指主体对客体表达正面情感或负面情感时的强弱程度,不同的情感程度往往是通过不同的情感词或情感语气等来体现。例如:“敬爱”与“亲爱”都是表达正面情感,同为褒义词。但是“敬爱”远比“亲爱”在表达情感程度上要强烈。通常在情感倾向分析研究中,为了区分两者的程度差别,采取给每个情感词赋予不同的权值来体现。
目前,情感倾向分析的方法主要分为两类:一种是基于情感词典的方法;一种是基于机器学习的方法,如基于大规模语料库的机器学习。前者需要用到标注好的情感词典,英文的词典有很多,中文主要有知网整理的情感词典Hownet和台湾大学整理发布的NTUSD两个情感词典,还有哈工大信息检索研究室开源的《同义词词林》可以用于情感词典的扩充。基于机器学习的方法则需要大量的人工标注的语料作为训练集,通过提取文本特征,构建分类器来实现情感的分类。
文本情感分析的分析粒度可以是词语、句子也可以是段落或篇章。段落篇章级情感分析主要是针对某个主题或事件进行倾向性判断,一般需要构建对应事件的情感词典,如电影评论的分析,需要构建电影行业自己的情感词典效果会比通用情感词典效果更好;也可以通过人工标注大量电影评论来构建分类器。句子级的情感分析大多事通过计算句子里包含的所有情感词的平均值来得到。
篇章级的情感分析,也可以通过聚合篇章中所有的句子的情感倾向来计算得出。因此,针对句子级的情感倾向分析,既能解决较短文本的情感分析,同时也可以是篇章级文本情感分析的基础。本文正是根据这一思路,设计的情感分析算法。
算法主要由三部分组成:
1、文本切割转换
算法设计的最大分析对象为篇章,最小对象为句子,我们可以把句子视作特例——单句的篇章,故算法分析的对象为文档D。
Paragraph = Document.split(“/n”) ## 将文档以换行符”/n”分割成段落P
Sentence = Paragraph.split( punc ) punc = [“。”,”;”,”?”,”!”] ## 将段落用中文里常用的句号、分号、问号、感叹号等划分句意的符号,切割成不同的句子L
Group = Sentence.split(“,”) ## 用逗号划分出句子里的意群(表示情感的最小单元)
Seg( each Group ) ##调用在线分词工具或者本地分词函数,对意群进行分词
开源中文分词工具有很多,如在线的SCWS(PHP),张华平博士团队开发的NLPIR(C、Python、Java),哈工大的LTP(C++、Python),还有R语言的分词包RWordseg(NLPIR的R接口)。几款分词工具各有各自的特点,在这里不详细介绍了,读者可以自行检索查阅。
文本切割的目的是将文本变成我们后续分析需要的格式,如句子“我今天很不高兴。”,进行文本切割后,转换成:
[(1,“我”,“r”),(2,“今天”,”t”),(3,“很”,”d”),(4,“不”,”d”),(5,“高兴”,“a”)]
选择不同的分词工具,可以获得不同的词语属性,用SCWS分词,还可以获得每个词的IDF值;用LTP分词,可以获得句子的依存关系、语义角色等。这些属性对于我们后面计算句子的情感倾向都是有帮助的。本文只用都了词语的词性,感兴趣的读者可以思考如何用其他的属性来实现更好的情感分析。
2、情感定位
本文基于已有的中文情感词库,构建了一张情感词表,然后对文本进行中文分词处理,将处理后得到的单词依次与预先构建好的情感词表逐个查找,若能找到,则是情感词,并读取情感极性及相应权值,否则,不是情感词,则进入下一个候选单词,直至整句话判断结束。
过程可以表示如下:
For each Paragraph in Document:
For each Line in Paragraph:
For each Group in Line:
For each Word in Group:
If word in senDict:
senWord = (句中位置,情感倾向,情感强度)
文本的情感分析是从发现句中的情感词开始,通过情感词的倾向和倾向度,来决定句子的情感,从而决定整个文本的情感。但是我们在实际生活中会发现,否定词的修饰会使情感词语的情感极性发生改变。比如:“我今天很不高兴”,该句中“高兴”是褒义词,由于否定词“不”的修饰,使其情感极性发生了改变,转变成了负面情感。由于汉语中存在多重否定现象,即当否定词出现奇数次时,表示否定意思;当否定词出现偶数次时,表示肯定意思。本文单独构建了一个否定词典notDict,并设置其权值为-1,常见的否定词如:不、没、无、非、莫、弗、毋、勿、未、否、别、無、休。
对否定词的处理过程可以简化为:
For each Paragraph in Document:
For each Line in Paragraph:
For each Group in Line:
For each Word in Group:
If word in senDict:
senWord = (句中位置,情感倾向,情感强度)
LastSenWordPosition = 0 ##上一个情感词在句中的位置
for i in range(senWord[0],LastSenWordPosition,-1):
if Group[i] in notDict:
notWord.append( (句中位置,-1) )
LastSenWordPosition = senWord[0]
另外,当程度副词修饰情感词,该情感词的情感倾向程度发生了变化。比如: “今天坐了12个小时的车,身体极度疲惫。”,“疲惫”是一个贬义词,前面一个程度副词“极度”的修饰使得“疲惫”原来的情感倾向程度发生了变化,这比没有修饰之前更加强烈。因此,为了准确表达文本的情感倾向,需做相应的权值调整。本文中的程度副词来源于知网(HowNet),选用“情感分析用词语集(beta版)”中的“中文程度级别词语”共219 个,蔺璜等人提出了把程度副词划分六个等级,笔者为每个程度副词定义了一个权重,被程度副词修饰后的情感词其权值应做相应调整。程度副词如下表所示:
程度副词示例
type 权值
超|over 1.5
很|very 1.25
极其|extreme / 最|most 2
较|more 1.2
欠|insufficiently 0.5
稍|-ish 0.8
程度副词的处理过程跟否定词类似,过程简化如下:
For each Paragraph in Document:
For each Line in Paragraph:
For each Group in Line:
For each Word in Group:
If word in senDict:
senWord = (句中位置,情感倾向,情感强度)
LastSenWordPosition = 0 ##上一个情感词在句中的位置
for i in range(senWord[0],LastSenWordPosition,-1):
if Group[i] in degreeDict:
degreeWord = ( (句中位置,修饰强度) )
LastSenWordPosition = senWord[0]
经过这样的处理,文本被进一步转换格式:
“我今天很不高兴。”
①经过文本切割转换
[(1,“我”,“r”),(2,“今天”,”t”),(3,“很”,”d”),(4,“不”,”d”),(5,“高兴”,“a”)]
②情感定位
[(5,“Happy”,4),[(4,-1)],(3,1.25)] ##[情感词,否定词,程度副词]
3、情感聚合
本文在前面说过,篇章级情感倾向通过聚合篇章中所有的句子的情感倾向来计算得出。句子级由句子中所含情感词来计算。通过前两步的操作,我们完成了句子意群的划分,同时也提出了每个意群里的情感词、否定词和程度副词。有了这些,下面我们先求出意群的情感值:
情感群—情感值 = 否定词-1 * 程度词权重 * 情感词权重
我们在实际应用中又发现,当一个句子中同时出现否定词和程度词时,由于否定词和程度词相对位置的不同,会引起情感的不同,比如:
“我很不高兴”——分词之后: 我 很 不 高兴
“我不很高兴”——分词之后: 我 不 很 高兴
可以看出,第一句话表达的是一种很强烈的负面情感,而第二句话则表达的是一种较弱的正面情感。因此,如果否定词在程度词之前,起到的是减弱的作用;如果否定词在程度词之后,则起到的是逆向情感的作用。所以我们对上述算法做了一下调整:
W = 1
If 位置(否定词)> 位置(程度词):
W = -1
意群情感值 = W * 程度词权重 * 情感词权重
If 位置(否定词)< 位置(程度词):
W = 0.5
意群情感值 = W * 程度词权重 * 情感词权重
如果意群里出现多个否定词,则处理办法为:
For n in notWord:
W = -1 * W
句子是由意群组成,故句子的情感我们可以简单记做:
句子情感值 = sum(意群情感值1,意群情感值2……)
段落是由不同的句子组成,但是考虑到段落的长短变化很大,故放弃用求和的方式来计算情感值,改为求平均值:
段落情感值 = average(句子1情感值,句子2情感值……)
文档是由不同的段落组成,同理,不同文档有不同的段落,故我们同样求平均值:
文档情感值 = average(段落1情感值,段落2情感值……)
以上是情感值的计算,至于情感倾向,首先可以通过情感值的符号来判断情感倾向是正向还是负向,若情感倾向不止正、负、中立这三种情况,还有更细的划分,则可以根据情感正负的情况,把对应的情感倾向进行汇总来表述。
上述的做法是最简单的做法,没有考虑太多句子之间的差异以及不同段落对文档的重要性。
本算法还有很多值得改进的地方,比如句子是由词语根据一定的语言规则构成的,应该把句子中词语的依存关系纳入到句子情感的计算过程中去,可根据句子依存关系,从句子的根节点开始对每个词进行情感倾向计算,根据句子依存关系求出句子的情感倾向和情感值。文档的情感,也应该根据句子的不同重要程度来计算,根据句子对文档的重要程度赋予不同权重,调整其对文档情感的贡献程度。确定句子的重要程度,可以根据句子在文档中的位置,根据句子中所含信息量的大小,句子中所含关键词的多少等等。
笔者按照这个思路,用python写了一百多行的代码实现了上述的算法,测试了一番,效果还可以,但词典的精度还需改进。
图片链接
![]() |
对《圣经》文本进行的情感分析 来自:视物致知
|
openbible.info使用 Viralheat Sentiment Analysis API对圣经所做的情感分析以及可视化。
参考文献:
陈晓东. (2012). 基于情感词典的中文微博情感倾向分析研究 (Master’s thesis, 华中科技大学).
王飞跃,李晓晨,毛文吉,王涛. (2013). 社会计算的基本方法与应用 (pp. 36-49). 浙江大学出版社.
rzcoding. Python 文本挖掘:使用情感词典进行情感分析(算法及程序设计). http://rzcoding.blog.163.com/blog/static/2222810172013101844033170/