近期老師給咱們安排了一個大做業,要求根據情感詞典對微博語料進行情感分析。因而在網上狂找資料,看相關書籍,終於搞出了這個任務。如今作作筆記,總結一下本次的任務,同時也給遇到有一樣需求的人,提供一點幫助。html
一、情感分析含義
情感分析指的是對新聞報道、商品評論、電影影評等文本信息進行觀點提取、主題分析、情感挖掘。情感分析經常使用於對某一篇新聞報道積極消極分析、淘寶商品評論情感打分、股評情感分析、電影評論情感挖掘。情感分析的內容包括:情感的持有者分析、態度持有者分析、態度類型分析(一系列類型如喜歡(like),討厭(hate),珍視(value),渴望(desire)等;或着簡單的加權極性如積極(positive),消極(negative)和中性(neutral)並可用具體的權重修飾)、態度的範圍分析(包含每句話,某一段、或者全文)。所以,情感分析的目的能夠分爲:初級:文章的總體感情是積極/消極的;進階:對文章的態度從1-5打分;高級:檢測態度的目標,持有者和類型。python
總的來講,情感分析就是對文本信息進行情感傾向挖掘。算法
二、情感挖掘方法
情感挖掘目前主要使用的方法是使用情感詞典,對文本進行情感詞匹配,彙總情感詞進行評分,最後獲得文本的情感傾向。本次我主要使用了兩種方法進行情感分析。第一種:基於BosonNLP情感詞典。該情感詞典是由波森天然語言處理公司推出的一款已經作好標註的情感詞典。詞典中對每一個情感詞進行情感值評分,bosanNLP情感詞典以下圖所示:app
第二種,採用的是知網推出的情感詞典,以及極性表進行情感分析。知網提供的情感詞典共用12個文件,分爲英文和中文。其中中文情感詞典包括:評價、情感、主張、程度(正面、負面)的情感文本。本文將評價和情感詞整合做爲情感詞典使用,程度詞表中含有的程度詞,按照等級區分,分爲:most(最高)-very(很、很是)-more(更多、更)-ish(稍、一點點)-insufficiently(欠、不)-over(過多、多分、多)六個情感程度詞典。函數
知網情感詞典下載地址:- http://www.keenage.com/html/c_bulletin_2007.htm工具
三、原理介紹
3.1 基於BosonNLP情感分析原理
基於BosonNLP情感詞典的情感分析較爲簡單。首先,須要對文本進行分句、分詞,本文選擇的分詞工具爲哈工大的pyltp。其次,將分詞好的列表數據對應BosonNLp詞典進行逐個匹配,並記錄匹配到的情感詞分值。最後,統計計算分值總和,若是分值大於0,表示情感傾向爲積極的;若是小於0,則表示情感傾向爲消極的。原理框圖以下:post
3.2 基於BosonNLP情感分析代碼:
# -*- coding:utf-8 -*- import pandas as pd import jieba #基於波森情感詞典計算情感值 def getscore(text): df = pd.read_table(r"BosonNLP_dict\BosonNLP_sentiment_score.txt", sep=" ", names=['key', 'score']) key = df['key'].values.tolist() score = df['score'].values.tolist() # jieba分詞 segs = jieba.lcut(text,cut_all = False) #返回list # 計算得分 score_list = [score[key.index(x)] for x in segs if(x in key)] return sum(score_list) #讀取文件 def read_txt(filename): with open(filename,'r',encoding='utf-8')as f: txt = f.read() return txt #寫入文件 def write_data(filename,data): with open(filename,'a',encoding='utf-8')as f: f.write(data) if __name__=='__main__': text = read_txt('test_data\微博.txt') lists = text.split('\n') # al_senti = ['無','積極','消極','消極','中性','消極','積極','消極','積極','積極','積極', # '無','積極','積極','中性','積極','消極','積極','消極','積極','消極','積極', # '無','中性','消極','中性','消極','積極','消極','消極','消極','消極','積極' # ] al_senti = read_txt(r'test_data\人工情感標註.txt').split('\n') i = 0 for list in lists: if list != '': # print(list) sentiments = round(getscore(list),2) #情感值爲正數,表示積極;爲負數表示消極 print(list) print("情感值:",sentiments) print('人工標註情感傾向:'+al_senti[i]) if sentiments > 0: print("機器標註情感傾向:積極\n") s = "機器判斷情感傾向:積極\n" else: print('機器標註情感傾向:消極\n') s = "機器判斷情感傾向:消極"+'\n' sentiment = '情感值:'+str(sentiments)+'\n' al_sentiment= '人工標註情感傾向:'+al_senti[i]+'\n' #文件寫入 filename = 'result_data\BosonNLP情感分析結果.txt' write_data(filename,'情感分析文本:') write_data(filename,list+'\n') #寫入待處理文本 write_data(filename,sentiment) #寫入情感值 write_data(filename,al_sentiment) #寫入機器判斷情感傾向 write_data(filename,s+'\n') #寫入人工標註情感 i = i+1
相關文件:學習
BosonNLp情感詞典下載地址:https://bosonnlp.com/dev/resource測試
微博語料:連接:https://pan.baidu.com/s/1Pskzw7bg9qTnXD_QKF-4sg 提取碼:15buspa
輸出結果:
3.3 基於知網情感詞典的情感挖掘原理
基於知網情感詞典的情感分析原理分爲如下幾步:
一、首先,須要對文本分句,分句,獲得分詞分句後的文本語料,並將結果與哈工大的停用詞表比對,去除停用詞;
二、其次,對每一句話進行情感分析,分析的方法主要爲:判斷這段話中的情感詞數目,含有積極詞,則積極詞數目加1,含有消極詞,則消極詞數目加1。而且再統計的過程當中還須要判斷該情感詞前面是否存在程度副詞,若是存在,則須要根據程度副詞的種類賦予不一樣的權重,乘以情感詞數。若是句尾存在?!等符號,則情感詞數目增長必定值,由於!與?這類的標點每每表示情感情緒的增強,所以須要進行必定處理。
三、接着統計計算整段話的情感值(積極詞值-消極詞值),獲得該段文本的情感傾向。
四、最後,統計每一段的情感值,相加獲得文章的情感值。
總體流程框圖以下:
3.4 基於知網情感詞典的情感分析代碼:
import pyltp from pyltp import Segmentor from pyltp import SentenceSplitter from pyltp import Postagger import numpy as np #讀取文件,文件讀取函數 def read_file(filename): with open(filename, 'r',encoding='utf-8')as f: text = f.read() #返回list類型數據 text = text.split('\n') return text #將數據寫入文件中 def write_data(filename,data): with open(filename,'a',encoding='utf-8')as f: f.write(str(data)) #文本分句 def cut_sentence(text): sentences = SentenceSplitter.split(text) sentence_list = [ w for w in sentences] return sentence_list #文本分詞 def tokenize(sentence): #加載模型 segmentor = Segmentor() # 初始化實例 # 加載模型 segmentor.load(r'E:\tool\python\Lib\site-packages\pyltp-0.2.1.dist-info\ltp_data\cws.model') # 產生分詞,segment分詞函數 words = segmentor.segment(sentence) words = list(words) # 釋放模型 segmentor.release() return words #詞性標註 def postagger(words): # 初始化實例 postagger = Postagger() # 加載模型 postagger.load(r'E:\tool\python\Lib\site-packages\pyltp-0.2.1.dist-info\ltp_data\pos.model') # 詞性標註 postags = postagger.postag(words) # 釋放模型 postagger.release() #返回list postags = [i for i in postags] return postags # 分詞,詞性標註,詞和詞性構成一個元組 def intergrad_word(words,postags): #拉鍊算法,兩兩匹配 pos_list = zip(words,postags) pos_list = [ w for w in pos_list] return pos_list #去停用詞函數 def del_stopwords(words): # 讀取停用詞表 stopwords = read_file(r"test_data\stopwords.txt") # 去除停用詞後的句子 new_words = [] for word in words: if word not in stopwords: new_words.append(word) return new_words # 獲取六種權值的詞,根據要求返回list,這個函數是爲了配合Django的views下的函數使用 def weighted_value(request): result_dict = [] if request == "one": result_dict = read_file(r"E:\學習筆記\NLP學習\NLP code\情感分析3\degree_dict\most.txt") elif request == "two": result_dict = read_file(r"E:\學習筆記\NLP學習\NLP code\情感分析3\degree_dict\very.txt") elif request == "three": result_dict = read_file(r"E:\學習筆記\NLP學習\NLP code\情感分析3\degree_dict\more.txt") elif request == "four": result_dict = read_file(r"E:\學習筆記\NLP學習\NLP code\情感分析3\degree_dict\ish.txt") elif request == "five": result_dict = read_file(r"E:\學習筆記\NLP學習\NLP code\情感分析3\degree_dict\insufficiently.txt") elif request == "six": result_dict = read_file(r"E:\學習筆記\NLP學習\NLP code\情感分析3\degree_dict\inverse.txt") elif request == 'posdict': result_dict = read_file(r"E:\學習筆記\NLP學習\NLP code\情感分析3\emotion_dict\pos_all_dict.txt") elif request == 'negdict': result_dict = read_file(r"E:\學習筆記\NLP學習\NLP code\情感分析3\emotion_dict\neg_all_dict.txt") else: pass return result_dict print("reading sentiment dict .......") #讀取情感詞典 posdict = weighted_value('posdict') negdict = weighted_value('negdict') # 讀取程度副詞詞典 # 權值爲2 mostdict = weighted_value('one') # 權值爲1.75 verydict = weighted_value('two') # 權值爲1.50 moredict = weighted_value('three') # 權值爲1.25 ishdict = weighted_value('four') # 權值爲0.25 insufficientdict = weighted_value('five') # 權值爲-1 inversedict = weighted_value('six') #程度副詞處理,對不一樣的程度副詞給予不一樣的權重 def match_adverb(word,sentiment_value): #最高級權重爲 if word in mostdict: sentiment_value *= 8 #比較級權重 elif word in verydict: sentiment_value *= 6 #比較級權重 elif word in moredict: sentiment_value *= 4 #輕微程度詞權重 elif word in ishdict: sentiment_value *= 2 #相對程度詞權重 elif word in insufficientdict: sentiment_value *= 0.5 #否認詞權重 elif word in inversedict: sentiment_value *= -1 else: sentiment_value *= 1 return sentiment_value #對每一條微博打分 def single_sentiment_score(text_sent): sentiment_scores = [] #對單條微博分句 sentences = cut_sentence(text_sent) for sent in sentences: #查看分句結果 # print('分句:',sent) #分詞 words = tokenize(sent) seg_words = del_stopwords(words) #i,s 記錄情感詞和程度詞出現的位置 i = 0 #記錄掃描到的詞位子 s = 0 #記錄情感詞的位置 poscount = 0 #記錄積極情感詞數目 negcount = 0 #記錄消極情感詞數目 #逐個查找情感詞 for word in seg_words: #若是爲積極詞 if word in posdict: poscount += 1 #情感詞數目加1 #在情感詞前面尋找程度副詞 for w in seg_words[s:i]: poscount = match_adverb(w,poscount) s = i+1 #記錄情感詞位置 # 若是是消極情感詞 elif word in negdict: negcount +=1 for w in seg_words[s:i]: negcount = match_adverb(w,negcount) s = i+1 #若是結尾爲感嘆號或者問號,表示句子結束,而且倒序查找感嘆號前的情感詞,權重+4 elif word =='!' or word =='!' or word =='?' or word == '?': for w2 in seg_words[::-1]: #若是爲積極詞,poscount+2 if w2 in posdict: poscount += 4 break #若是是消極詞,negcount+2 elif w2 in negdict: negcount += 4 break i += 1 #定位情感詞的位置 #計算情感值 sentiment_score = poscount - negcount sentiment_scores.append(sentiment_score) #查看每一句的情感值 # print('分句分值:',sentiment_score) sentiment_sum = 0 for s in sentiment_scores: #計算出一條微博的總得分 sentiment_sum +=s return sentiment_sum # 分析test_data.txt 中的全部微博,返回一個列表,列表中元素爲(分值,微博)元組 def run_score(contents): # 待處理數據 scores_list = [] for content in contents: if content !='': score = single_sentiment_score(content) # 對每條微博調用函數求得打分 scores_list.append((score, content)) # 造成(分數,微博)元組 return scores_list #主程序 if __name__ == '__main__': print('Processing........') #測試 # sentence = '要怎麼說呢! 我須要的戀愛不是如今的樣子, 但願是能互相鼓勵的勉勵, 你如今的樣子讓我以爲很困惑。 你到底能不能陪我一直走下去, 你是否有決心?是否你看不慣我?你是能夠隨意的生活,可是個人將來我耽誤不起!' # sentence = '轉有用嗎?這個事原本就是要全社會共同努力的,公交公司有沒有培訓到位?公交車上地鐵站內有沒有放足夠的宣傳標語?我如今轉一下微博,沒有多大的意義。' sentences = read_file(r'test_data\微博.txt') scores = run_score(sentences) #人工標註情感詞典 man_sentiment = read_file(r'test_data\人工情感標註.txt') al_sentiment = [] for score in scores: print('情感分值:',score[0]) if score[0] < 0: print('情感傾向:消極') s = '消極' elif score[0] == 0: print('情感傾向:中性') s = '中性' else: print('情感傾向:積極') s = '積極' al_sentiment.append(s) print('情感分析文本:',score[1]) i = 0 #寫入文件中 filename = r'result_data\result_data.txt' for score in scores: write_data(filename, '情感分析文本:{}'.format(str(score[1]))+'\n') #寫入情感分析文本 write_data(filename,'情感分值:{}'.format(str(score[0]))+'\n') #寫入情感分值 write_data(filename,'人工標註情感:{}'.format(str(man_sentiment[i]))+'\n') #寫入人工標註情感 write_data(filename, '機器情感標註:{}'.format(str(al_sentiment[i]))+'\n') #寫入機器情感標註 write_data(filename,'\n') i +=1 print('succeed.......')
輸出結果:
四、小結
本次的情感分析程序完成簡單的情感傾向判斷,準確率上基於BosonNLP的情感分析較低,其情感分析準確率爲:56.67%;而基於知網情感詞典的情感分析準確率達到90%,效果上仍是不錯的。可是,這兩個程序都還只是情感分析簡單使用,並未涉及到更深奧的算法,若是想要更加精確,或者再更大樣本中得到更高精度,這兩個情感分析模型仍是不夠的。可是用來練習學習仍是不錯的選擇。要想更深刻的理解和弄得情感分析,還須要繼續學習。
PS:須要基於知網情感詞典的情感分析詞典數據,能夠在評論中留下你的郵箱,我發給你。