1. 程式人生 > >基於LVD、貝葉斯模型演算法實現的電商行業商品評論與情感分析案例

基於LVD、貝葉斯模型演算法實現的電商行業商品評論與情感分析案例

一、 專案需求

現在大家進行網購,在購物之前呢,肯定會看下相關商品的評論,看下好評和差評,然後再綜合衡量,最後才會決定是否購買相關的商品。對一個指定商品,生產商,賣家,買家認同該商品的哪些優點/不認同那些。

評論分析:
A、電商評論的重要性 ------ 消費者先看評論,然後決定是否下單 B、電商評論太多時遇到的問題--------銷量多,評論數大 C、提取有價值的評論----去除灌水評論(例如:好評,東西很好;商品很贊等)
專案的輸出:
商品好評–/差評–若干個topic中,其關鍵詞以及權重
1.1 語言處理相關庫(snownlp,jieba,gensim)

安裝與機器學習,自然語言處理相關庫,在Anaconda Prompt

下輸入:

pip install snownlp              # 處理自然語言庫/情感分析
pip install jieba                # 中文分詞
pip install gensim               # 機器學習演算法/自然語言相關的功能 

gensim.corpora.dictionary.Dictionary的函式 doc2bow(document)
document-->片語成的列表list,這個list中有些詞是重複的,也缺少每個詞的詞頻。
需要先用 doc2bow 函式將資料轉換成恰當的格式。

這裡寫圖片描述

1.2 LDA主題模型

比方說,如果一篇文章是在講狗的,那“狗”和“骨頭”等詞出現的頻率會高些;講貓的,那“貓”和“魚”等詞出現的頻率會高些。在這裡,”狗”就是一個topic,”貓”也是一個topic。 詞袋模型(bag of words)只考慮頻數,不考慮詞序,混亂的

LDA (Latent Dirichlet allocation)主題模型
1 已知條件: 某些文件的都是由那些詞構成的 2 假定條件: LDA 模型假設每一篇文章都在講述若干個主題topic,可以人為的設定k 值 3 求解: 通過LDA 模型,可以求出K個主題中,每個主題到底長成什麼樣子。
  • 能做: 求解出K個主題長什麼樣子
  • 不能做:不能人為設定主題,不能人為設定什麼是財經,體育,科技。 LDA是無監督學習,模型訓練後,每個主題是什麼就是什麼

LDA 思想

  • LDA是一個貝葉斯模型(Bayers model)。之前的樸素貝葉斯只是其中一個。只不過LDA更復雜些
  • 在貝葉斯模型中,根據可見 —推出—> 不可見, 例如: 打噴嚏:–>(夏天)可能是嗆著了 –>(冬天)可能是感冒了
  • LDA模型優點 1 無監督:無需勞心勞力的去對訓練資料做標註 2 預處理簡單:分詞,去停用詞 3 引數少,一般只需要設定引數K (K表示一拱多少個主題)
1.3 相關模型的比較

除了LDA技術,SVD(奇異值分解)技術也可以應用於主題模型分析。

問題: LSI與LSA有什麼區別?
技術是相同的,都是採用SVD降維,而且都是處理自然語言中的term-document矩陣。 一般LSI專指索引和搜尋領域。

二、程式碼:

2.1 匯入資料—評論提取—文字去重
#匯入資料-評論提取
import pandas as pd

inputfile = '.\\data\\huizong.csv'              #彙總檔案
outputfile = '.\\data\\meidi_jd.txt'	        #評論提取儲存路徑
data = pd.read_csv(inputfile,encoding = 'utf-8')
data = data[[u'評論']][data[u'品牌'] == u'美的']
data.to_csv(outputfile,index = False,header = False,encoding = 'utf-8')

#文字去重
inputfile = '.\\data\\meidi_jd.txt'             #評論檔案
outputfile = '.\\data\\meidi_jd_process_1.txt'  #評論處理後儲存路徑
data = pd.read_csv(inputfile, encoding = 'utf-8', header = None)
data=data.dropna()     
l1 = len(data)
data = pd.DataFrame(data[0].unique())
l2 = len(data)
data.to_csv(outputfile, index = False, header = False, encoding = 'utf-8')
print(u'刪除了%s條評論。' %(l1 - l2))

#機械壓縮去詞
def cutword(strs,reverse=False):
        s1=[]
        s2=[]
        s=[]
        if reverse :
            strs=strs[::-1]
        s1.append(strs[0])
        for i in strs[1:]:
            if i==s1[0] :
                if len(s2)==0:
                    s2.append(i)
                else :
                    if s1==s2:
                        s2=[]
                        s2.append(i)
                    else:
                        s=s+s1+s2
                        s1=[]
                        s2=[]
                        s1.append(i)
            else :
                if s1==s2 and len(s1)>=2 and len(s2)>=2:
                    s=s+s1
                    s1=[]
                    s2=[]
                    s1.append(i)
                else:
                    if len(s2)==0:
                        s1.append(i)
                    else :
                        s2.append(i)
        if s1==s2:
            s=s+s1
        else:
            s=s+s1+s2
        if reverse :
            #print ''.join(s[::-1])
            return ''.join(s[::-1])
        else:
            #print ''.join(s)
            return ''.join(s)
			
data2 = data.iloc < [:,0].apply(cutword)
data2 = data2.apply(cutword,reverse = True)

#短句過濾
data3 = data2[data2.apply(len) >= 4]
2.2 模型構造—情感分析—分詞—去除停用
#情感分析
from snownlp import SnowNLP

coms = []
coms = data3.apply(lambda x:SnowNLP(x).sentiments)

data1 = data3[coms >= 0.5]              # 大於0.5為積極的情緒詞
data2 = data3[coms < 0.5]

#分詞
import jieba
mycut = lambda s: ''.join(jieba.cut(s))	# 自定義簡單分詞函式,分詞用空格隔開
data1 = data1.apply(mycut)              # 通過廣播進行分詞,加快速度
data2 = data2.apply(mycut)

#outputfile1 = 'd:/data/example08/meidi_jd_pos_cut.txt'
#outputfile2 = 'd:/data/example08/meidi_jd_neg_cut.txt'
#data1.to_csv(outputfile1,index = False,header = False,encoding = 'utf-8')	#儲存結果
#data2.to_csv(outputfile2,index = False,header = False,encoding = 'utf-8')	#儲存結果

#去除停用(與評論無關的詞)
stoplist = '.\\data\\stoplist.txt'
stop = pd.read_csv(stoplist,encoding = 'utf-8',
                   header = None,sep = 'tipdm')	    #sep設定一個不存在的分割詞 tipdm

stop = [' ',''] + list(stop[0])	                    #Pandas 自動過濾空格符,這裡是手動新增

pos = pd.DataFrame(data1[:5000])
neg = pd.DataFrame(data1[:5000])

neg[1] = neg[0].apply(lambda s: s.split(' '))	                #定義一個分割詞,用apply廣播
neg[2] = neg[1].apply(lambda x:[i for i in x if i not in stop]) #逐詞判斷是否為停用詞
pos[1] = neg[0].apply(lambda s: s.split(' '))
pos[2] = neg[1].apply(lambda x [i for i in x if i not in stop])
2.3 LDA主題分析
from gensim import corpora,models

#負面主題分析
neg_dict = corpora.Dictionary(neg[2])	            #建立詞典
neg_corpus = [neg_dict.doc2bow(i) for i in neg[2]]  #建立語料庫
neg_lda = models.LdaModel(neg_corpus,num_topics = 3,id2word = neg_dict)	#LDA模型訓練
for i in range(3):
	print('topic' + str(i))
	print(neg_lda.print_topic(i))                   #輸出每個主題
	
#正面主題分析
pos_dict = corpora.Dictionary(pos[2])	            #建立詞典
pos_corpus = [pos_dict.doc2bow(i) for i in pos[2]]	#建立語料庫
pos_lda = models.LdaModel(pos_corpus,num_topics = 3,id2word = pos_dict)	#LDA模型訓練
for i in range(3):
	print('topic' + str(i))
	print(pos_lda.print_topic(i))	                #輸出每個主題