select * from hotel_comment_datas group by `評論ID`
特征工程
利用特征工程獲取相應評論的內容,需將文本信息轉為相應的數值
(1)獲取評論內容,做相應的索引(對所有的評論做處理)
import pandas as pd sql = '''select * from hotel_comment_datas group by `評論ID`''' data = pd.read_sql(sql, conn) # 去除標簽列所對應的缺失值,可以使用花式索引的方式,對於數據進行相應的清洗和替換 data = data[['評論內容', '評分']].replace('none', np.NaN) data = data.dropna() # 刪除評論內容和用戶評分為空的數據
(2)開始分詞----cut
comment = data['評論內容'] # print(comment) # (2)開始分詞----cut list_word = [] # 創建空列表用來接收相應的結果 for i in comment: a = list(jieba.cut(i)) # 按照列表的方式進行相應的分詞 list_word.append(' '.join(a))
(3)對於分詞后的文本進行相應的特征抽取,TF-TDF特征抽取。TF表示關鍵詞的頻率,TDF表示逆文檔的頻率,主要用來表示每個關鍵字在文檔的重要性
# TF-IDF 特征抽取 from sklearn.feature_extraction.text import TfidfVectorizer tf = TfidfVectorizer() # 調用TF-TDF分詞算法,將文本轉化為頻率 data1 = tf.fit_transform(list_word) # 先擬合,再轉換,得出一個稀疏矩陣
對因變量(住客評分)進行相應的分類
分類代碼
bq = [] for i in data['評分']: # 初始的分類級別 if float(i) <= 0: bq.append(0) elif 0 < float(i) <= 1: bq.append(1) elif 1 < float(i) <= 2: bq.append(2) elif 2 < float(i) <= 3: bq.append(3) elif 3 < float(i) <= 4: bq.append(4) else: bq.append(5)
划分數據集
(1)找到相對應的特征(自變量)x,標簽y(因變量)
x = data2
y = bq
(2)划分相應的訓練集和測試集,其中訓練集為80%,測試集為20%
# 划分數據集 from sklearn.model_selection import train_test_split x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=0)
(3)對數據進行標准化(將自變量的數據進行相應的標准化處理,可以使得某一個特征不會對總的結果產生較大影響)
# 對數據進行標准化處理 from sklearn.preprocessing import StandardScaler ss = StandardScaler() # print(ss.fit_transform(x_train)) # 標准化后,有的值為正,有的值為負 x_train = ss.fit_transform(x_train) x_test = ss.fit_transform(x_test)
數學建模-朴素貝葉斯分類算法
利用貝葉斯分類的目的:依據對應的評論內容給這個結果進行預測打分和客戶實際打分的區別
- 預測打分可以將客戶評價分級,(分級的結果acc准確率要求比較高)
- 進一步:分級后,將不同等級的用戶,單獨提取出來,按照預測的打分結果,產生新的一列
- 按照預測評分結果,按照預測結果的不同等級,將整個數據划分為三個級別,需進一步考慮
- 對於不同級別的顧客,可以考慮做相應的評價畫像
- 同樣可以考慮做顧客畫像
代碼實現
from sklearn.naive_bayes import GaussianNB # 用於處理有正有負的數據 nb = GaussianNB() # 因為稀疏矩陣標准化后的值很可能是負值 nb.fit(x_train, y_train) # 擬合相應的訓練集 x_predict = nb.predict(x_test) # 放入相應的測試集進行分類 t_predict = nb.predict(x_train) # 放入相應的訓練集進行分類 score_1 = nb.score(x_train, y_train) # 使用對應的訓練集測試一下評估的ACC score_2 = nb.score(x_test, y_test) print(score_1, score_2)
模型的准確性
模型調優
增加相應的特征(如評論的推薦數)
這個特征,所有評論特征數,我們可以通過篩選所有評論特征數來提高我們的數據質量(數據的可靠性),進而提高我們的數學模型的ACC(准確率)
# 在sql部分重新篩選所有評論推薦數大於1的數據 sql = '''select * from hotel_comment_datas where `所有評論推薦數` >1 group by `評論ID`'''
與未使用所有評論推薦數的特征的模型准確率,相比,訓練集的ACC提高了將近7個百分點,測試集的ACC降低了6個百分點
可以考慮分類級別過多
我們是對酒店進行分類,一般我們對酒店的評價是差、一般、好;但是我們之前是划分了5個等級,我們考慮一下是否分類過度,導致模型ACC過低?嘗試降低分類數
縮小分類級別 for i in data['評分']: if float(i) <= 2: bq.append(0) elif 2 < float(i) <= 4: bq.append(1) else: bq.append(2)
相比與上圖的數學模型ACC而言,本次的訓練集數學模型ACC提高了近1個百分點 ,測試集數學模型ACC基本一致
修改訓練集(70%)與測試集(30%)的占比
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.3, random_state=0)
相比上圖的數學模型ACC而言,本次訓練集的數學模型ACC提高近2個百分點,測試集的數學模型ACC提高近0.8個百分點
增加特征,重新篩選數據
select * from hotel_comment_datas where `所有評論推薦數` >1 and `城市足跡數` >1 group by `評論ID`
此時我們發現,我們的數學模型的ACC非常好
酒店數學建模代碼

# --encoding:utf-8-- # Yun import numpy as np import pandas as pd import sklearn from pprint import pprint # TF-IDF 特征抽取 from sklearn.feature_extraction.text import TfidfVectorizer # 對數據進行標准化處理 from sklearn.preprocessing import StandardScaler # 引入朴素貝葉斯算法 from sklearn.naive_bayes import GaussianNB # 用於處理有正有負的數據 from sklearn.naive_bayes import MultinomialNB # 用於處理有正數的數據 # 划分數據集 from sklearn.model_selection import train_test_split # 對所有的評論內容分開 import jieba import pymysql config = { 'host': '127.0.0.1', 'port': 3306, 'user': 'root', 'password': '123456', 'db': 'xiecheng_cruise', 'charset': 'utf8' } # 步驟一:連接數據庫並進行數據清洗 # 連接數據庫 conn = pymysql.connect(**config) # 獲取MSC地中海郵輪·地中海輝煌號5天4晚福岡游輪旅游的評論 # sql = '''select * from cruise_comment where cruise_name="MSC地中海郵輪·地中海輝煌號5天4晚福岡" group by comment_id''' sql = '''select * from hotel_comment_datas where `所有評論推薦數` >1 and `城市足跡數` >1 group by `評論ID`''' data = pd.read_sql(sql, conn) # 去除標簽列所對應的缺失值,可以使用花式索引的方式,對於數據進行相應的清洗和替換 data = data[['評論內容', '評分']].replace('none', np.NaN) data = data.dropna() # 刪除評論內容和用戶評分為空的數據 # 步驟二:對因變量進行相應的分類 # 需要對標簽進行相應的分類 bq = [] # for i in data['評分']: # 初始的分類級別 # if float(i) <= 0: # bq.append(0) # elif 0 < float(i) <= 1: # bq.append(1) # elif 1 < float(i) <= 2: # bq.append(2) # elif 2 < float(i) <= 3: # bq.append(3) # elif 3 < float(i) <= 4: # bq.append(4) # # else: # bq.append(5) # 降低分類級別 for i in data['評分']: if float(i) <= 2: bq.append(0) elif 2 < float(i) <= 4: bq.append(1) else: bq.append(2) # print(bq) # 步驟三:利用特征工程獲取相應評論的內容,需將文本信息轉為相應的數值 # (1)獲取評論內容,做相應的索引(對所有的評論做處理) comment = data['評論內容'] # print(comment) # (2)開始分詞----cut list_word = [] # 創建空列表用來接收相應的結果 for i in comment: a = list(jieba.cut(i)) # 按照列表的方式進行相應的分詞 list_word.append(' '.join(a)) # print(list_word) # (3)對於分詞后的文本進行相應的特征抽取,TF-TDF特征抽取。TF表示關鍵詞的頻率, # TDF表示逆文檔的頻率,主要用來表示每個關鍵字在文檔的重要性 tf = TfidfVectorizer() # 調用TF-TDF分詞算法,將文本轉化為頻率 data1 = tf.fit_transform(list_word) # 先擬合,再轉換,得出一個稀疏矩陣 # print(data1) print('關鍵詞的數量:', len(tf.get_feature_names())) # 查看一下分詞之后關鍵詞的數量 data2 = data1.toarray() # 將產生的稀疏矩陣轉化為相應的數組 # pprint(data2) # 步驟四:划分數據集 # 需將數據集進行相應的划分,train test # (1)找到相對應的特征(自變量)x,標簽y(因變量) x = data2 y = bq # (2)划分相應的訓練集和測試集,其中訓練集為80%,測試集為20% # 為了演示結果一致,可以考慮使用隨機種子設置0 x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=0) # print(x_train, y_train) # (3)對數據進行標准化 ss = StandardScaler() # print(ss.fit_transform(x_train)) # 標准化后,有的值為正,有的值為負 x_train = ss.fit_transform(x_train) x_test = ss.fit_transform(x_test) # 步驟五:正式引入貝葉斯算法,進行相應的分類-------朴素貝葉斯算法原理 # 利用貝葉斯分類的目的:依據對應的評論內容給這個結果進行預測打分和客戶實際打分的區別。 # 預測打分可以將客戶評價分級,(分級的結果acc准確率要求比較高) # 進一步:分級后,將不同等級的用戶,單獨提取出來,按照預測的打分結果,產生新的一列 # 預測評分結果,按照預測結果的不同等級,將整個數據划分為三個級別,進一步考慮:對於不同級別的顧客 # 做相應的評價畫像(同樣可以考慮做顧客畫像) nb = GaussianNB() # 因為稀疏矩陣標准化后的值很可能是負值 nb.fit(x_train, y_train) # 擬合相應的訓練集 x_predict = nb.predict(x_test) # 放入相應的測試集進行分類 t_predict = nb.predict(x_train) # 放入相應的訓練集進行分類 # print(x_predict) print('================================================================') # print(t_predict) score_1 = nb.score(x_train, y_train) # 使用對應的訓練集測試一下評估的ACC score_2 = nb.score(x_test, y_test) print(score_1, score_2) # 步驟六:模型優化,增加相應的特征---我們在抽取數據的時候考慮進一步篩選數據 # 在數據篩選的時候考慮多個字段,在sql部分直接處理 # 可以考慮分類的級別過多,減少分類的個數,在對應的標簽處處理,發現對於總的評論而言 # 模型的准確率提升,並且,發現評論的推薦數,這個字段非常有用,可以提高整個模型的准確率(ACC)
酒店所有評論的詞雲圖
酒店差評詞雲圖
詞雲繪制代碼

# --encoding:utf-8-- # Yun import numpy as np import pandas as pd import pymysql from jieba import analyse # 運用此模塊做相對應的分詞處理----提取關鍵詞 from PIL import Image # 處理圖片 from matplotlib import pyplot as plt from wordcloud import WordCloud, ImageColorGenerator config = { 'host': '127.0.0.1', 'port': 3306, 'user': 'root', 'password': '123456', 'db': 'xiecheng_cruise', 'charset': 'utf8' } # 步驟一:連接數據庫並進行數據清洗 # 連接數據庫 conn = pymysql.connect(**config) # 依據貝葉斯分類方法提取的數據方式是一樣的 sql = '''select * from hotel_bad_comment_datas where 所有評論推薦數>1 and 酒店ID='662464' GROUP BY 評論ID''' # sql = '''select * from hotel_comment_datas where `所有評論推薦數` >1 and `城市足跡數` >1 group by `評論ID`''' data = pd.read_sql(sql, conn) print(data) # 清理none值,否則會成為高頻詞匯 data1 = data['評論內容'].replace('none', np.NaN).dropna() # 刪除評論內容為空的數據 # 處理數據,生成關鍵詞的占比權重,此時的data1是Series數據 # 分詞是對於整個數據而言 data2 = data1.to_list() # 將Series數據轉化為列表,為了做下一步的拼接 data3 = ''.join(data2) # print(data3) # 提取對應的關鍵詞,並查看這些關鍵詞對應的權重 result = analyse.textrank(data3, topK=50, withWeight=True) print(result) dict_1 = {} for i in result: dict_1[i[0]] = i[1] # print(dict_1) # 生成對應的詞雲 # 利用PIL的Image打開背景圖片,並且進行相應的參數化 img = Image.open('timg2.jpg') graph = np.array(img) # 把img的參數給到graph生成相應的詞雲 # WordCloud默認不支持中文,加載對應的中文黑色字體庫,一般在電腦的C盤 fonts # mask以傳遞過來的數據繪制詞雲 wc = WordCloud(font_path='C:\Windows\Fonts\simhei.ttf', background_color='white', max_words=300, mask=graph) # 將字典的文本生成相對應的詞雲 wc.generate_from_frequencies(dict_1) # 進一步,基於背景顏色,設置字體的顏色 image_color = ImageColorGenerator(graph) # 顯示對應的圖片 plt.imshow(wc) # 顯示對應的詞雲圖 plt.axis('off') # 關閉圖像對應的坐標 plt.show() # 顯示對應的窗口 # 將生成的圖片保存 wc.to_file('H:\大數據分析\攜程輿情分析\酒店差評詞雲.jpg') # 考慮到這是多個酒店的差評的詞雲,考慮將單一酒店的詞雲圖提取出來, # 在sql數據篩選階段修改篩選條件 # 例如通過酒店ID篩選每個酒店的差論詞雲