1. 程式人生 > >電商商品評論主題分析(LDA)

電商商品評論主題分析(LDA)

下面程式碼的意思是從評論資料中抽取品牌是美的的資料(15-1)

#-*- coding: utf-8 -*-  
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')  

這裡一句話概括接下來的去重概念,文字去重和機械壓縮去重

文字去重指的是資料條之間的去重。

機械壓縮去重指的是資料條內部,詞語與詞語之間的去重。

下面程式碼是用來文字去重的(15-2)。

#-*- coding: utf-8 -*-  
import pandas as pd  
  
inputfile = '../data/meidi_jd.txt' #評論檔案  
outputfile = '../data/meidi_jd_process_1.txt' #評論處理後儲存路徑  
data = pd.read_csv(inputfile, encoding = 'utf-8', header = None)  
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))  

下面程式碼的作用是把評論前面的評分刪除(15-3):

#-*- coding: utf-8 -*-  
import pandas as pd  
  
#引數初始化  
inputfile1 = '../data/meidi_jd_process_end_負面情感結果.txt'  
inputfile2 = '../data/meidi_jd_process_end_正面情感結果.txt'  
outputfile1 = '../data/meidi_jd_neg.txt'  
outputfile2 = '../data/meidi_jd_pos.txt'  
  
data1 = pd.read_csv(inputfile1, encoding = 'utf-8', header = None) #讀入資料  
data2 = pd.read_csv(inputfile2, encoding = 'utf-8', header = None)  
print("data1=",data1[0])  
  
data1 = pd.DataFrame(data1[0].str.replace('.*?\d+?\\t ', '')) #用正則表示式修改資料  
data2 = pd.DataFrame(data2[0].str.replace('.*?\d+?\\t ', ''))#這裡的意思其實是用‘’(也就是代表什麼都沒有)來代替前面的符合特徵的字串,等效於實現了刪除的功能  
print("###############################")  
print("data1=",data1[0])  
#以上正則表示式的效果,可以通過把正則篩選前後的data[0]分別輸出來進行比較  
data1.to_csv(outputfile1, index = False, header = False, encoding = 'utf-8') #儲存結果  
data2.to_csv(outputfile2, index = False, header = False, encoding = 'utf-8')  
接下來是進行分詞(詳細解釋請見程式碼中註釋)(15-4)
#-*- coding: utf-8 -*-
import pandas as pd
import jieba #匯入結巴分詞,需要自行下載安裝

#引數初始化
inputfile1 = '../data/meidi_jd_neg.txt'
inputfile2 = '../data/meidi_jd_pos.txt'
outputfile1 = '../data/meidi_jd_neg_cut.txt'
outputfile2 = '../data/meidi_jd_pos_cut.txt'

data1 = pd.read_csv(inputfile1, encoding = 'utf-8', header = None) #讀入資料
data2 = pd.read_csv(inputfile2, encoding = 'utf-8', header = None)

mycut = lambda s: ' '.join(jieba.cut(s)) #自定義簡單分詞函式,先識別句子中的中文單詞,然後把中文單詞通過空格連線起來
#上面一句程式碼中,s是入口引數,.join前面的空格表示把jieba庫處理過後的s中的詞語jieba.cut(s),用空格來連線。
data1 = data1[0].apply(mycut) #通過“廣播”形式分詞,加快速度。
data2 = data2[0].apply(mycut)

data1.to_csv(outputfile1, index = False, header = False, encoding = 'utf-8') #儲存結果
data2.to_csv(outputfile2, index = False, header = False, encoding = 'utf-8')

接下來是去除停用詞

#-*- coding: utf-8 -*-  
import pandas as pd  
  
#引數初始化  
negfile = '../data/meidi_jd_neg_cut.txt'  
posfile = '../data/meidi_jd_pos_cut.txt'  
stoplist = '../data/stoplist.txt'  
  
neg = pd.read_csv(negfile, encoding = 'utf-8', header = None) #讀入資料  
pos = pd.read_csv(posfile, encoding = 'utf-8', header = None)  
stop = pd.read_csv(stoplist, encoding = 'utf-8', header = None, sep = 'tipdm',engine='python')  
#sep設定分割詞,由於csv預設以半形逗號為分割詞,而該詞恰好在停用詞表中,因此會導致讀取出錯(這裡的出錯的意思就是程式碼執行報錯,編譯器直接不讓編譯通過)  
#所以解決辦法是手動設定一個不存在的分割詞,如tipdm。  
#這裡先解釋下什麼是“停用詞”,停用詞指的是本文中出現頻率很高、但是實際意義不大的詞語,比如  
#“今天好嗨森啊啊啊啊啊啊啊啊”,那麼這句話中的“啊啊啊啊啊啊啊啊”就是停用詞  
#講通俗點的話,停用詞就是“廢話”。  。  
  
stop = [' ', ''] + list(stop[0]) #Pandas自動過濾了空格符,這裡手動新增(在每條資料的開頭加個空格)  
  
#下面這段程式碼可以分為兩小段,這兩小段程式碼幾乎一致,前面一個是針對負面評論,後一個是針對正面評論,所以只詳解其中一個  
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]) #逐詞判斷是否停用詞,思路同上  
#上面這句程式碼的語法是:列表推導式子。意思是說,如果i不在停用詞列表(stop)中,就保留該詞語(也就是最前面的一個i),否則就進行刪除  
#上面的這句程式碼中,把for i in x看做整體,把if i not in stop看做判斷語句,把最前面的i看做滿足if語句之後的執行語句即可。  
pos[1] = pos[0].apply(lambda s: s.split(' '))  
pos[2] = pos[1].apply(lambda x: [i for i in x if i not in stop])  
  
#上面的lamda s和lamda x中的s和x都是表示入口引數,apply的意思是,把apply前面的字串當做入口引數,輸入到appy後面所定義的函式中  

最後是建立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):  
  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)  
for i in range(3):  
  neg_lda.print_topic(i) #輸出每個主題  

結果類似於:

 0.065*"安裝" + 0.025*"熱水器" + 0.020*"說" + 0.017*"買" + 0.017*"美的" + 0.016*"師傅" + 0.012*"元" + 0.011*"京東" + 0.009*"售後" + 0.009*"安裝費"
0.035*"安裝" + 0.023*"加熱" + 0.023*"不錯" + 0.013*"東西" + 0.011*"沒用" + 0.011*"送貨" + 0.010*"熱水器" + 0.009*"師傅" + 0.009*"速度" + 0.009*"不好"
0.031*"買" + 0.031*"不錯" + 0.016*"安裝" + 0.014*"熱水器" + 0.010*"價格" + 0.009*"加熱" + 0.007*"元" + 0.007*"速度" + 0.007*"質量" + 0.006*"京東" 

通俗解釋下LDA演算法幹嘛的,我們知道:

K-means是聚類的,他主要是處理資料的,對資料進行聚類。

LDA其實也是聚類的,主要是處理字串的,對字串進行聚類。