1. 程式人生 > >基於Python的情感分析案例

基於Python的情感分析案例

情感分析:又稱為傾向性分析和意見挖掘,它是對帶有情感色彩的主觀性文字進行分析、處理、歸納和推理的過程,其中情感分析還可以細分為情感極性(傾向)分析,情感程度分析,主客觀分析等。

情感極性分析的目的是對文字進行褒義、貶義、中性的判斷。在大多應用場景下,只分為兩類。例如對於“喜愛”和“厭惡”這兩個詞,就屬於不同的情感傾向。

背景交代:爬蟲京東商城某一品牌紅酒下所有評論,區分好評和差評,提取特徵詞,用以區分新的評論【出現品牌名稱可以忽視,本文章不涉及打廣告哦 o(╯□╰)o】。

示例1(好評)
這裡寫圖片描述

示例2(差評)
這裡寫圖片描述

讀取文字檔案

def text():
     f1 = open('E:/工作檔案/情感分析案例1/good.txt'
,'r',encoding='utf-8') f2 = open('E:/工作檔案/情感分析案例1/bad.txt','r',encoding='utf-8') line1 = f1.readline() line2 = f2.readline() str = '' while line1: str += line1 line1 = f1.readline() while line2: str += line2 line2 = f2.readline() f1.close() f2.close() return
str

把單個詞作為特徵

def bag_of_words(words):
     return dict([(word,True) for word in words])

print(bag_of_words(text()))

這裡寫圖片描述

import nltk
from nltk.collocations import  BigramCollocationFinder
from nltk.metrics import  BigramAssocMeasures

把雙個詞作為特徵,並使用卡方統計的方法,選擇排名前1000的雙詞

def  bigram(words,score_fn=BigramAssocMeasures.chi_sq,n=1000
)
:
bigram_finder=BigramCollocationFinder.from_words(words) #把文字變成雙詞搭配的形式 bigrams = bigram_finder.nbest(score_fn,n) #使用卡方統計的方法,選擇排名前1000的雙詞 newBigrams = [u+v for (u,v) in bigrams] return bag_of_words(newBigrams) print(bigram(text(),score_fn=BigramAssocMeasures.chi_sq,n=1000))

這裡寫圖片描述

把單個詞和雙個詞一起作為特徵

def  bigram_words(words,score_fn=BigramAssocMeasures.chi_sq,n=1000):
     bigram_finder=BigramCollocationFinder.from_words(words)
     bigrams = bigram_finder.nbest(score_fn,n)
     newBigrams = [u+v for (u,v) in bigrams]
     a = bag_of_words(words)
     b = bag_of_words(newBigrams)
     a.update(b)  #把字典b合併到字典a中
     return a 

print(bigram_words(text(),score_fn=BigramAssocMeasures.chi_sq,n=1000))

這裡寫圖片描述

結巴分詞工具進行分詞及詞性標註
三種分詞模式 :
A、精確模式:試圖將句子最精確地切開,適合文字分析。預設是精確模式。
B、全模式:把句子中所有的可以成詞的詞語都掃描出來, 速度非常快,但是不能解決歧義
C、搜尋引擎模式:在精確模式的基礎上,對長詞再次切分,提高召回率,適合用於搜尋引擎分詞
注:當指定jieba.cut的引數HMM=True時,就有了新詞發現的能力。

import jieba

def read_file(filename):
     stop = [line.strip() for line in  open('E:/工作檔案/情感分析案例1/stop.txt','r',encoding='utf-8').readlines()]  #停用詞
     f = open(filename,'r',encoding='utf-8')
     line = f.readline()
     str = []
     while line:
         s = line.split('\t')
         fenci = jieba.cut(s[0],cut_all=False)  #False預設值:精準模式
         str.append(list(set(fenci)-set(stop)))
         line = f.readline()
     return str

安裝nltk,pip3 install nltk

from nltk.probability import  FreqDist,ConditionalFreqDist
from nltk.metrics import  BigramAssocMeasures

獲取資訊量最高(前number個)的特徵(卡方統計)

def jieba_feature(number):   
     posWords = []
     negWords = []
     for items in read_file('E:/工作檔案/情感分析案例1/good.txt'):#把集合的集合變成集合
         for item in items:
            posWords.append(item)
     for items in read_file('E:/工作檔案/情感分析案例1/bad.txt'):
         for item in items:
            negWords.append(item)

     word_fd = FreqDist() #可統計所有詞的詞頻
     cond_word_fd = ConditionalFreqDist() #可統計積極文字中的詞頻和消極文字中的詞頻

     for word in posWords:
         word_fd[word] += 1
         cond_word_fd['pos'][word] += 1

     for word in negWords:
         word_fd[word] += 1
         cond_word_fd['neg'][word] += 1

     pos_word_count = cond_word_fd['pos'].N() #積極詞的數量
     neg_word_count = cond_word_fd['neg'].N() #消極詞的數量
     total_word_count = pos_word_count + neg_word_count

     word_scores = {}#包括了每個詞和這個詞的資訊量

     for word, freq in word_fd.items():
         pos_score = BigramAssocMeasures.chi_sq(cond_word_fd['pos'][word],  (freq, pos_word_count), total_word_count) #計算積極詞的卡方統計量,這裡也可以計算互資訊等其它統計量
         neg_score = BigramAssocMeasures.chi_sq(cond_word_fd['neg'][word],  (freq, neg_word_count), total_word_count) 
         word_scores[word] = pos_score + neg_score #一個詞的資訊量等於積極卡方統計量加上消極卡方統計量

     best_vals = sorted(word_scores.items(), key=lambda item:item[1],  reverse=True)[:number] #把詞按資訊量倒序排序。number是特徵的維度,是可以不斷調整直至最優的
     best_words = set([w for w,s in best_vals])
     return dict([(word, True) for word in best_words])

調整設定,分別從四種特徵選取方式開展並比較效果

def build_features():
     #feature = bag_of_words(text())#第一種:單個詞
     #feature = bigram(text(),score_fn=BigramAssocMeasures.chi_sq,n=500)#第二種:雙詞
     #feature =  bigram_words(text(),score_fn=BigramAssocMeasures.chi_sq,n=500)#第三種:單個詞和雙個詞
     feature = jieba_feature(300)#第四種:結巴分詞

     posFeatures = []
     for items in read_file('E:/工作檔案/情感分析案例1/good.txt'):
         a = {}
         for item in items:
            if item in feature.keys():
                a[item]='True'
         posWords = [a,'pos'] #為積極文字賦予"pos"
         posFeatures.append(posWords)
     negFeatures = []
     for items in read_file('E:/工作檔案/情感分析案例1/bad.txt'):
         a = {}
         for item in items:
            if item in feature.keys():
                a[item]='True'
         negWords = [a,'neg'] #為消極文字賦予"neg"
         negFeatures.append(negWords)
     return posFeatures,negFeatures

獲得訓練資料

posFeatures,negFeatures =  build_features()
from random import shuffle
shuffle(posFeatures) 
shuffle(negFeatures) #把文字的排列隨機化  
train =  posFeatures[300:]+negFeatures[300:]#訓練集(70%)
test = posFeatures[:300]+negFeatures[:300]#驗證集(30%)
data,tag = zip(*test)#分離測試集合的資料和標籤,便於驗證和測試
def score(classifier):
     classifier = SklearnClassifier(classifier) 
     classifier.train(train) #訓練分類器
     pred = classifier.classify_many(data) #給出預測的標籤
     n = 0
     s = len(pred)
     for i in range(0,s):
         if pred[i]==tag[i]:
            n = n+1
     return n/s #分類器準確度

這裡需要安裝幾個模組:scipy、numpy、sklearn
scipy及numpy模組需要訪問http://www.lfd.uci.edu/~gohlke/pythonlibs,找到scipy、numpy,下載對應版本的whl

import sklearn
from nltk.classify.scikitlearn import  SklearnClassifier
from sklearn.svm import SVC, LinearSVC,  NuSVC
from sklearn.naive_bayes import  MultinomialNB, BernoulliNB
from sklearn.linear_model import  LogisticRegression
from sklearn.metrics import  accuracy_score
print('BernoulliNB`s accuracy is %f'  %score(BernoulliNB()))
print('MultinomiaNB`s accuracy is %f'  %score(MultinomialNB()))
print('LogisticRegression`s accuracy is  %f' %score(LogisticRegression()))
print('SVC`s accuracy is %f'  %score(SVC()))
print('LinearSVC`s accuracy is %f'  %score(LinearSVC()))
print('NuSVC`s accuracy is %f'  %score(NuSVC()))

檢測結果輸出1(單個詞:每個字為特徵)
這裡寫圖片描述

檢測結果輸出2(詞[倆字]:2個字為特徵,使用卡方統計選取前n個資訊量大的作為特徵)
這裡寫圖片描述

檢測結果輸出3(單個詞和雙詞:把前面2種特徵合併之後的特徵)
這裡寫圖片描述

檢測結果輸出4(結巴分詞:用結巴分詞外加卡方統計選取前n個資訊量大的作為特徵)
這裡寫圖片描述

對比四種特徵選取方式可以看出,單字 - 詞 - 單字+詞 - 結巴分詞,效果是越來越好的。