自然語言處理(NLP)中的詞雲圖繪制、情感分析、LDA主題分析


一、本案例采集京東網站熱水器不同品牌的評論數據進行分析

1.導入數據

1 import pandas as pd
2 data = pd.read_csv('comment.csv')
3 data.head()

2.數據探索

①繪制各品牌的銷售情況

1 brand_dis = data['品牌'].value_counts()  #統計各類品牌的銷量.sort_values()
2 import matplotlib.pyplot as plt
3 plt.rcParams['font.sans-serif'] = 'SimHei'
4 plt.pie(brand_dis,autopct='%0.2f%%',labels=brand_dis.index)
5 plt.legend(loc =[1,0.5])
6 plt.show()

 ②由於海爾品牌銷售最好,以下主要分析海爾品牌熱水器

1 import re
2 plt.rcParams['font.sans-serif'] = 'SimHei'
3 label =haier.reset_index()['index'].apply(lambda x:re.sub('[海爾\(Haier\)|海爾\(Haier\) ]','',x))
4 plt.bar(range(len(haier)),haier.values)
5 plt.title('海爾銷售前10的型號')
6 plt.xticks(range(len(haier)),label,rotation=290)
7 plt.show()

 

 3.數據預處理

①首先取出評論字段所有數據

1 comment_text = data['評論'].drop_duplicates()  #去重

 ②提出前面標紅的無關內容

 1 comment_text  =comment_text.dropna()   #去除空值,否則做.apply(lambda x:x.replace('\\n',''))執行報錯
 2 comment_text = comment_text.apply(lambda x:x.replace('\\n',''))  #去除\n符號
 3 comment_text = comment_text.apply(lambda x:re.sub('&[a-z]+;','',x))  #去除網頁……類型字符
 4 
 5 #自定義函數(剔除空調型號)
 6 lt = pd.Series(data["型號"].unique()).dropna() #品牌類型
 7 def drop_brand(x):
 8     for i in lt:
 9         try:
10             x = re.sub(i,'',x)
11         except:
12             pass
13     return x
14 
15 comment_text = comment_text.apply(drop_brand)   #剔除評論中包含的品牌名

 ③取出海爾品牌的所有評論

1 comment_haier = comment_text[data['品牌']=='海爾']

④jieba分詞並剔除停用詞和空行

1 #結巴分詞
2 import jieba
3 haier_cut = comment_haier.apply(jieba.lcut)
4 stop_word = pd.read_csv('stopword.txt',encoding='gbk',sep='haha',header=None)
5 stop_word = [',','',' ']+list(stop_word[0])
6 haier_stop = haier_cut.apply(lambda x:[i for i in x if i not in stop_word])  #剔除停用詞
7 haier_stop = haier_stop[haier_stop.apply(lambda x:len(x)!=0)] #去除空行

⑤統計詞頻

1 #統計詞頻
2 tem_lt = []
3 [tem_lt.append(j) for i in haier_stop for j in i]
4 
5 haier_count = pd.Series(tem_lt).value_counts()

⑥繪制詞雲圖

1 #繪制詞雲圖
2 import matplotlib.pyplot as plt
3 from wordcloud import WordCloud
4 mask = plt.imread('duihuakuan.jpg')
5 wc = WordCloud(font_path='C:/Windows/Fonts/simhei.ttf',mask=mask,background_color='white')
6 wc.fit_words(haier_count)
7 plt.imshow(wc)

 4.情感傾向分析

①導入情感詞典

 1 score = pd.read_csv('BosonNLP_sentiment_score.txt',sep =' ',header=None)  #導入情感詞評分
 2 score.columns = ['word','score']
 3 
 4 not_word = pd.read_csv('not.csv')  #導入否定詞
 5 not_word.columns=['notword']
 6 not_word['notscore']=-1
 7 
 8 degree = pd.read_csv('degree.csv')   #導入副詞
 9 degree.columns = ['degreeword','descore']
10 degree['descore']/=-100

②定義情感評分函數及調用

 1 def get_score(x=None):   #x=None是可以直接被appl調用
 2     tem_d = pd.DataFrame(x,columns=['word1'])
 3     td_s = pd.merge(tem_d,score,how='left',left_on='word1',right_on='word')
 4     tds_d = pd.merge(td_s,degree,how='left',left_on='word1',right_on='degreeword')
 5     index = tds_d[tds_d['descore'].notna()].index
 6     length = len(tem_d)
 7 
 8     for i in index:
 9         if i<length-1:
10             tds_d['score'][i+1]*=tds_d['descore'][i]
11 
12     tdsd_n = pd.merge(tds_d,not_word,how='left',left_on='word1',right_on='notword')
13     index1 = tdsd_n[tdsd_n['notscore'].notna()].index
14 
15     for i in index1:
16         if i<length-1:
17             tdsd_n['score'][i+1]=tdsd_n['score'][i+1]*tdsd_n['notscore'][i]
18     return tdsd_n['score'].sum()
19 
20 y =haier_stop.apply(get_score)

③划分情感

1 # 划分正面評論與負面評論
2 ind = y > 0
3 message_ = data_after_stop.apply(lambda x: ' '.join(x))
4 message_[ind].to_csv('hai_pcomment.txt',index=False)
5 message_[-ind].to_csv('hai_ncomment.txt',index=False)

5.LDA分析

①導入數據

1 pos_com = pd.read_csv('hai_pcomment.txt',header=None)
2 neg_com = pd.read_csv('hai_ncomment.txt',header=None)
1 pos_com.columns = ['comment']
2 pos_com['comment'] = pos_com['comment'].str.split(' ')
3 pos_com

 ②數據准備及轉為字典和詞袋

1 from gensim.corpora import Dictionary
2 
3 pos_com = list(pos_com['comment'])  #轉化為二維數組
4 
5 dic = Dictionary(pos_com)  #構成詞典
6 
7 corpus = [dic.doc2bow(i) for i in pos_com]  #詞袋形象地解釋便是:將文本中的詞放入一個袋子里,在袋子中,詞擁有兩個屬性編號和數目(id,num)。
#一個詞袋對應一篇文檔。由元組(id,num)構成的 [(0, 1), (1, 2), (2, 1)] 則稱作稀疏向量。一般語料庫都是用這種方式來表示(gensim中)。

③LDA訓練及最佳主題選擇

LDA訓練

 1 def choose_topic(corpus,dic):
 2         '''
 3         @description: 生成模型
 4         @param 
 5         @return: 生成主題數分別為1-15的LDA主題模型,並保存起來。
 6         '''
 7         for i in range(1,16):
 8             print('目前的topic個數:{}'.format(i))
 9             temp = 'lda_{}'.format(i)
10             tmp = LdaModel(corpus, num_topics=i, id2word=dic, passes=20)
11             file_path = './{}.model'.format(temp)
12             tmp.save(file_path)
13             print('------------------')

 加載模型並通過困惑度評價主題個數

 1 def plot_perplexity(corpus):
 2     x_list = []
 3     y_list = []
 4     for i in range(1,16):
 5         temp_model = 'lda_{}.model'.format(i)
 6         try:
 7             lda = models.ldamodel.LdaModel.load(temp_model)
 8             perplexity = lda.log_perplexity(corpus)  #計算困惑度,困惑度越低越好
 9             x_list.append(i)
10             y_list.append(perplexity)
11         except Exception as e:
12             print(e)
13     plt.rcParams['']
14     plt.plot(x_list, y_list)
15     plt.xlabel('num topics')
16     plt.ylabel('perplexity score')
17     plt.legend(('perplexity_values'), loc='best')
18     plt.show()
19 
20 plot_perplexity(corpus)

 由圖知,主題個數在9的時候下降較快。所以主題數為9可能合適。下面在看看一致性

 1 from gensim.models import CoherenceModel
 2 def visible_model(topic_num, corpus):
 3         '''
 4         @description: 可視化模型
 5         @param :topic_num:主題的數量
 6         @return: 可視化lda模型
 7         '''
 8         x_list = []
 9         y_list = []
10         for i in range(1,16):
11             temp_model = 'lda_{}.model'.format(i)
12             try:
13                 lda = models.ldamodel.LdaModel.load(temp_model)
14                 cv_tmp = CoherenceModel(model=lda, corpus=corpus, dictionary=dic,coherence='u_mass')
15                 #計算一致性
16                 x_list.append(i)
17                 y_list.append(cv_tmp.get_coherence())  
18             except:
19                 print('沒有這個模型:{}'.format(temp_model))
20         plt.rcParams['axes.unicode_minus'] = False
21         plt.plot(x_list, y_list)
22         plt.xlabel('num topics')
23         plt.ylabel('coherence score')
24         plt.legend(('coherence_values'), loc='best')
25         plt.show()
26 visible_model(16, corpus)

 一致性越高越好,由圖只,在主題數為1的時候合適,與上面困惑度相矛盾,因此根據分析需要進一步展開分析

④對模型可視化主題,進一步分析

1 import pyLDAvis.gensim  
2 from gensim import models
3 model_name =  'lda_2.model'   #兩個主題時
4 pos_model = models.ldamodel.LdaModel.load(model_name)
5 vis_data = pyLDAvis.gensim.prepare(pos_model, corpus, dic)
6 pyLDAvis.show(vis_data, open_browser=False)
  • 兩個主題時

 

由第一幅圖可知:安裝、師傅、送貨、海爾、京東、服務、熱水器可以看出海爾熱水器在京東上送貨、安裝、師傅態度各方面較好

由第一幅圖可知:不錯、海爾、加熱、買東西、質量、品牌、熱水器、挺、價格、便宜、外觀、值得  可以看出客戶對海爾熱水器的價格、外觀、品牌上有好的口碑

  •  三個主題時

 

 

 圖一可知:安裝、海爾、元、師傅、說、買、熱水器、棒、京東、安裝費、配件、花、材料費、收費、收、客服、裝、售后、貴、材料、裝修、費用 比前面兩個主題時增加了安裝費、材料費貴等不好的評價。所以綜合上,三個主題比較合理,好的服務可能會帶來額外的費用,畢竟人力成本高。

LDA參照知乎:https://www.zhihu.com/topic/19565464/hot


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM