基於LVD、貝葉斯模型演算法實現的電商行業商品評論與情感分析案例
阿新 • • 發佈:2018-12-11
一、 專案需求
現在大家進行網購,在購物之前呢,肯定會看下相關商品的評論,看下好評和差評,然後再綜合衡量,最後才會決定是否購買相關的商品。對一個指定商品,生產商,賣家,買家認同該商品的哪些優點/不認同那些。
- 評論分析:
- 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)) #輸出每個主題