学习情感分析相关知识。情感分析(SA)又称为倾向性分析和意见挖掘,它是对带有情感色彩的主观性文本进行分析、处理、归纳和推理的过程,其中情感分析还可以细分为情感极性(倾向)分析,情感程度分析,主客观分析等。情感极性分析的目的是对文本进行褒义、贬义、中性的判断。在大多应用场景下,只分为两类。例如对于“喜爱”和“厌恶”这两个词,就属于不同的情感倾向。现阶段主要的情感分析方法主要有两类:基于词典的方法基于机器学习的方法基于词典的方法主要通过制定一系列的情感词典和规则,对文本进行段落拆借、句法分析,计算情感值,最后通过情感值来作为文本的情感倾向依据。基于机器学习的方法大多将这个问题转化为一个分类问题来看待,对于情感极性的判断,将目标情感分类2类:正、负。对训练文本进行人工标标注,然后进行有监督的机器学习过程。例如想在较为常见的基于大规模语料库的机器学习等。
基于词典的中文情感倾向分析算法的认识
算法主要由三部分组成:
1、文本切割转换
算法设计的最大分析对象为篇章,最小对象为句子,我们可以把句子视作特例——单句的篇章,故算法分析的对象为文档D。Paragraph = Document.split(“/n”) ## 将文档以换行符”/n”分割成段落PSentence = Paragraph.split( punc ) punc = [“。”,”;”,”?”,”!”] ## 将段落用中文里常用的句号、分号、问号、感叹号等划分句意的符号,切割成不同的句子LGroup = 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情感值……)
以上是情感值的计算,至于情感倾向,首先可以通过情感值的符号来判断情感倾向是正向还是负向,若情感倾向不止正、负、中立这三种情况,还有更细的划分,则可以根据情感正负的情况,把对应的情感倾向进行汇总来表述。
上述的做法是最简单的做法,没有考虑太多句子之间的差异以及不同段落对文档的重要性。