注:本文轉(zhuǎn)載自知乎專欄
原文鏈接:https://zhuanlan.zhihu.com/p/23225934
情感分析就是分析一句話說(shuō)得是很主觀還是客觀描述赴邻,分析這句話表達(dá)的是積極的情緒還是消極的情緒。
原理
比如這么一句話:“這手機(jī)的畫面極好奸焙,操作也比較流暢彤敛。不過(guò)拍照真的太爛了!系統(tǒng)也不好玄糟“乐龋”
① 情感詞
要分析一句話是積極的還是消極的逢并,最簡(jiǎn)單最基礎(chǔ)的方法就是找出句子里面的情感詞砍聊,積極的情感詞比如:贊贰军,好,順手灶伊,華麗等寒跳,消極情感詞比如:差童太,爛胸完,壞,坑爹等爆惧。出現(xiàn)一個(gè)積極詞就+1锨能,出現(xiàn)一個(gè)消極詞就-1。
里面就有“好”熄阻,“流暢”兩個(gè)積極情感詞倔约,“爛”一個(gè)消極情感詞浸剩。那它的情感分值就是1+1-1+1=2. 很明顯這個(gè)分值是不合理的,下面一步步修改它吏恭。
② 程度詞
“好”袖扛,“流暢”和‘爛“前面都有一個(gè)程度修飾詞十籍〈浇福”極好“就比”較好“或者”好“的情感更強(qiáng)盏筐,”太爛“也比”有點(diǎn)爛“情感強(qiáng)得多。所以需要在找到情感詞后往前找一下有沒(méi)有程度修飾界牡,并給不同的程度一個(gè)權(quán)值漾抬。比如”極“纳令,”無(wú)比“,”太“就要把情感分值4圈匆,”較“捏雌,”還算“就情感分值2,”只算“纬傲,”僅僅“這些就0.5了窘奏。那么這句話的情感分值就是:41+12-14+1=3着裹。
③ 感嘆號(hào)
可以發(fā)現(xiàn)太爛了后面有感嘆號(hào),嘆號(hào)意味著情感強(qiáng)烈摔竿。因此發(fā)現(xiàn)嘆號(hào)可以為情感值+2. 那么這句話的情感分值就變成了:41+12-1*4-2+1 = 1
④ 否定詞
明眼人一眼就看出最后面那個(gè)”好“并不是表示”好“少孝,因?yàn)榍懊孢€有一個(gè)”不“字。所以在找到情感詞的時(shí)候袁翁,需要往前找否定詞。比如”不“柄驻,”不能“這些詞焙压。而且還要數(shù)這些否定詞出現(xiàn)的次數(shù)涯曲,如果是單數(shù),情感分值就-1拨黔,但如果是偶數(shù)傲武,那情感就沒(méi)有反轉(zhuǎn)揪利,還是1狠持。在這句話里面,可以看出”好“前面只有一個(gè)”不“甜刻,所以”好“的情感值應(yīng)該反轉(zhuǎn)正勒,-1章贞。
因此這句話的準(zhǔn)確情感分值是:41+12-14-2+1*-1 = -1
⑤ 積極和消極分開(kāi)來(lái)
再接下來(lái),很明顯就可以看出蜕径,這句話里面有褒有貶败京,不能用一個(gè)分值來(lái)表示它的情感傾向赡麦。而且這個(gè)權(quán)值的設(shè)置也會(huì)影響最終的情感分值帕识,敏感度太高了遂铡。因此對(duì)這句話的最終的正確的處理忧便,是得出這句話的一個(gè)積極分值,一個(gè)消極分值(這樣消極分值也是正數(shù)超歌,無(wú)需使用負(fù)數(shù)了)蒂教。它們同時(shí)代表了這句話的情感傾向凝垛。所以這句評(píng)論應(yīng)該是”積極分值:6,消極分值:7炭分。
⑥ 以分句的情感為基礎(chǔ)
再仔細(xì)一步剑肯,詳細(xì)一點(diǎn),一條評(píng)論的情感分值是由不同的分句加起來(lái)的呀忧,因此要得到一條評(píng)論的情感分值而账,就要先計(jì)算出評(píng)論中每個(gè)句子的情感分值因篇。這條例子評(píng)論有四個(gè)分句惜犀,因此其結(jié)構(gòu)如下([積極分值, 消極分值]):[[4, 0], [2, 0], [0, 6], [0, 1]] 。
以上就是使用情感詞典來(lái)進(jìn)行情感分析的主要流程了汽烦,算法的設(shè)計(jì)也會(huì)按照這個(gè)思路來(lái)實(shí)現(xiàn)莉御。
算法設(shè)計(jì)
第一步:讀取評(píng)論數(shù)據(jù)怨咪,對(duì)評(píng)論進(jìn)行分句。
第二步:查找對(duì)分句的情感詞煮岁,記錄積極還是消極,以及位置冶伞。
第三步:往情感詞前查找程度詞响禽,找到就停止搜尋荚醒。為程度詞設(shè)權(quán)值,乘以情感值侯繁。
第四步:往情感詞前查找否定詞巫击,找完全部否定詞精续,若數(shù)量為奇數(shù)粹懒,乘以-1凫乖,若為偶數(shù),乘以1删掀。
第五步:判斷分句結(jié)尾是否有感嘆號(hào)导街,有嘆號(hào)則往前尋找情感詞搬瑰,有則相應(yīng)的情感值+2控硼。
第六步:計(jì)算完一條評(píng)論所有分句的情感值卡乾,用數(shù)組(list)記錄起來(lái)缚够。
第七步:計(jì)算并記錄所有評(píng)論的情感值谍椅。
第八步:通過(guò)分句計(jì)算每條評(píng)論的積極情感均值,消極情感均值埂伦,積極情感方差思恐,消極情感方差胀莹。
實(shí)戰(zhàn)
這里是作者參考已有代碼,結(jié)合自己需要媳否,對(duì)代碼進(jìn)行了簡(jiǎn)單的修改篱竭。本腳本運(yùn)行環(huán)境是python3.5 步绸,使用2.x的盆友們見(jiàn)諒瓤介。
import jieba
import numpy as np
#打開(kāi)詞典文件,返回列表
def open_dict(Dict = 'hahah', path=r'/Users/apple888/PycharmProjects/Textming/Sent_Dict/Hownet/'):
path = path + '%s.txt' % Dict
dictionary = open(path, 'r', encoding='utf-8')
dict = []
for word in dictionary:
word = word.strip('\n')
dict.append(word)
return dict
def judgeodd(num):
if (num % 2) == 0:
return 'even'
else:
return 'odd'
#注意氯质,這里你要修改path路徑闻察。
deny_word = open_dict(Dict = '否定詞', path= r'/Users/apple888/PycharmProjects/Textming/')
posdict = open_dict(Dict = 'positive', path= r'/Users/apple888/PycharmProjects/Textming/')
negdict = open_dict(Dict = 'negative', path= r'/Users/apple888/PycharmProjects/Textming/')
degree_word = open_dict(Dict = '程度級(jí)別詞語(yǔ)', path= r'/Users/apple888/PycharmProjects/Textming/')
mostdict = degree_word[degree_word.index('extreme')+1 : degree_word.index('very')]#權(quán)重4蜓陌,即在情感詞前乘以3
verydict = degree_word[degree_word.index('very')+1 : degree_word.index('more')]#權(quán)重3
moredict = degree_word[degree_word.index('more')+1 : degree_word.index('ish')]#權(quán)重2
ishdict = degree_word[degree_word.index('ish')+1 : degree_word.index('last')]#權(quán)重0.5
def sentiment_score_list(dataset):
seg_sentence = dataset.split('。')
count1 = []
count2 = []
for sen in seg_sentence: #循環(huán)遍歷每一個(gè)評(píng)論
segtmp = jieba.lcut(sen, cut_all=False) #把句子進(jìn)行分詞填抬,以列表的形式返回
i = 0 #記錄掃描到的詞的位置
a = 0 #記錄情感詞的位置
poscount = 0 #積極詞的第一次分值
poscount2 = 0 #積極詞反轉(zhuǎn)后的分值
poscount3 = 0 #積極詞的最后分值(包括嘆號(hào)的分值)
negcount = 0
negcount2 = 0
negcount3 = 0
for word in segtmp:
if word in posdict: # 判斷詞語(yǔ)是否是情感詞
poscount += 1
c = 0
for w in segtmp[a:i]: # 掃描情感詞前的程度詞
if w in mostdict:
poscount *= 4.0
elif w in verydict:
poscount *= 3.0
elif w in moredict:
poscount *= 2.0
elif w in ishdict:
poscount *= 0.5
elif w in deny_word:
c += 1
if judgeodd(c) == 'odd': # 掃描情感詞前的否定詞數(shù)
poscount *= -1.0
poscount2 += poscount
poscount = 0
poscount3 = poscount + poscount2 + poscount3
poscount2 = 0
else:
poscount3 = poscount + poscount2 + poscount3
poscount = 0
a = i + 1 # 情感詞的位置變化
elif word in negdict: # 消極情感的分析,與上面一致
negcount += 1
d = 0
for w in segtmp[a:i]:
if w in mostdict:
negcount *= 4.0
elif w in verydict:
negcount *= 3.0
elif w in moredict:
negcount *= 2.0
elif w in ishdict:
negcount *= 0.5
elif w in degree_word:
d += 1
if judgeodd(d) == 'odd':
negcount *= -1.0
negcount2 += negcount
negcount = 0
negcount3 = negcount + negcount2 + negcount3
negcount2 = 0
else:
negcount3 = negcount + negcount2 + negcount3
negcount = 0
a = i + 1
elif word == '宏蛉!' or word == '!': ##判斷句子是否有感嘆號(hào)
for w2 in segtmp[::-1]: # 掃描感嘆號(hào)前的情感詞拾并,發(fā)現(xiàn)后權(quán)值+2鹏浅,然后退出循環(huán)
if w2 in posdict or negdict:
poscount3 += 2
negcount3 += 2
break
i += 1 # 掃描詞位置前移
# 以下是防止出現(xiàn)負(fù)數(shù)的情況
pos_count = 0
neg_count = 0
if poscount3 < 0 and negcount3 > 0:
neg_count += negcount3 - poscount3
pos_count = 0
elif negcount3 < 0 and poscount3 > 0:
pos_count = poscount3 - negcount3
neg_count = 0
elif poscount3 < 0 and negcount3 < 0:
neg_count = -poscount3
pos_count = -negcount3
else:
pos_count = poscount3
neg_count = negcount3
count1.append([pos_count, neg_count])
count2.append(count1)
count1 = []
return count2
def sentiment_score(senti_score_list):
score = []
for review in senti_score_list:
score_array = np.array(review)
Pos = np.sum(score_array[:, 0])
Neg = np.sum(score_array[:, 1])
AvgPos = np.mean(score_array[:, 0])
AvgPos = float('%.1f'%AvgPos)
AvgNeg = np.mean(score_array[:, 1])
AvgNeg = float('%.1f'%AvgNeg)
StdPos = np.std(score_array[:, 0])
StdPos = float('%.1f'%StdPos)
StdNeg = np.std(score_array[:, 1])
StdNeg = float('%.1f'%StdNeg)
score.append([Pos, Neg, AvgPos, AvgNeg, StdPos, StdNeg])
return score
data = '你就是個(gè)王八蛋之碗,混賬玩意!你們的手機(jī)真不好用季希!非常生氣式塌,我非常郁悶!R背馈>澄觥劳淆!'
data2= '我好開(kāi)心啊默赂,非常非常非常高興!今天我得了一百分曲掰,我很興奮開(kāi)心栏妖,愉快,開(kāi)心'
print(sentiment_score(sentiment_score_list(data)))
print(sentiment_score(sentiment_score_list(data2)))
運(yùn)行結(jié)果:
[[78.0, 169.0, 3.1, 6.8, 3.1, 6.5]]
[[327.0, 30.0, 14.9, 1.4, 22.5, 0.9]]
從得分我們看到第一段話是消極的宛裕,第二段是積極的论泛。(主要看Pos與Neg大衅ㄗ唷)
運(yùn)行代碼及詞典下載
鏈接:http://link.zhihu.com/?target=https%3A//pan.baidu.com/s/1jIRoOxK
密碼:6wq4
下載完代碼坟瓢,一定要注意代碼中的path,修改成泥電腦中的文件路徑粥诫,否則沒(méi)法用崭庸。有什么問(wèn)題可以給作者留言。
歡迎關(guān)注作者公眾號(hào):大鄧帶你玩轉(zhuǎn)python