基于LSTM电商评论情感分析-多评价指标可视化版(内附源码)【自然语言处理NLP-100例】
生活随笔
收集整理的這篇文章主要介紹了
基于LSTM电商评论情感分析-多评价指标可视化版(内附源码)【自然语言处理NLP-100例】
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
- 🔗 運行環(huán)境:python3
- 🚩 作者:K同學(xué)啊
- 🥇 精選專欄:《深度學(xué)習(xí)100例》
- 🔥 推薦專欄:《新手入門深度學(xué)習(xí)》
- 📚 選自專欄:《Matplotlib教程》
- 🧿 優(yōu)秀專欄:《Python入門100題》
大家好,我是K同學(xué)啊!
在上一篇文章中,我使用LSTM對電商評論做了一個較為復(fù)雜的情感分析,本文就繼續(xù)上次的工作做進一部分的分析。本次主要是在評價指標(biāo)metrics處增加了Precision、Recall、AUC等值,實現(xiàn)了訓(xùn)練模型的同時記錄這些指標(biāo),是實現(xiàn)方式上與以往也有所不同。與此同時,本次全連接層Dense的輸出也被設(shè)置為1,之前很少這樣操作的,可以對這塊針對性學(xué)習(xí)一下。
文章目錄
- 一、前期工作
- 1. 導(dǎo)入數(shù)據(jù)
- 2. 數(shù)據(jù)分析
- 二、數(shù)據(jù)預(yù)處理
- 1. 打亂數(shù)據(jù)
- 2. 分詞處理
- 3. 去除停用詞
- 4. Word2vec處理
- 5. 劃分訓(xùn)練集與測試集
- 三、結(jié)果分析
- 四、情感預(yù)測
一、前期工作
1. 導(dǎo)入數(shù)據(jù)
#源碼內(nèi)可閱讀 df| 用了一段時間,感覺還不錯,可以 | 正面 |
| 電視非常好,已經(jīng)是家里的第二臺了。第一天下單,第二天就到本地了,可是物流的人說車壞了,一直催... | 正面 |
| 電視比想象中的大好多,畫面也很清晰,系統(tǒng)很智能,更多功能還在摸索中 | 正面 |
| 不錯 | 正面 |
| 用了這么多天了,感覺還不錯。夏普的牌子還是比較可靠。希望以后比較耐用,現(xiàn)在是考量質(zhì)量的時候。 | 正面 |
| ... | ... |
| 一般,差強人意,還弄了點不愉快,投訴了好久才解決 | 負(fù)面 |
| 屏幕拐角明顯暗,圖像不到邊。工程師上門盡然說沒問題!退貨還要收100元的開箱費,幫別人買的,... | 負(fù)面 |
| 一分都不想給,京東這次讓我太失望了,買的電視沒有聲音,說是退貨上門取件,規(guī)定好的時間不去,一... | 負(fù)面 |
| 新電視買回家不到十多天,底座支架因質(zhì)量問題斷裂,電視從桌子上摔壞,打售后電話,人員一直推脫不... | 負(fù)面 |
| 一般般。這個價位也不會抱太多的期望。比某某TV還是好很多。 | 負(fù)面 |
4283 rows × 2 columns
2. 數(shù)據(jù)分析
df.groupby('label')["evaluation"].count() label 正面 1908 負(fù)面 2375 Name: evaluation, dtype: int64 df.label.value_counts().plot(kind='pie', autopct='%0.05f%%', colors=['lightblue', 'lightgreen'], explode=(0.01, 0.01)) <AxesSubplot:ylabel='label'> df['length'] = df['evaluation'].apply(lambda x: len(x)) df.head()| 用了一段時間,感覺還不錯,可以 | 正面 | 15 |
| 電視非常好,已經(jīng)是家里的第二臺了。第一天下單,第二天就到本地了,可是物流的人說車壞了,一直催... | 正面 | 97 |
| 電視比想象中的大好多,畫面也很清晰,系統(tǒng)很智能,更多功能還在摸索中 | 正面 | 33 |
| 不錯 | 正面 | 2 |
| 用了這么多天了,感覺還不錯。夏普的牌子還是比較可靠。希望以后比較耐用,現(xiàn)在是考量質(zhì)量的時候。 | 正面 | 46 |
二、數(shù)據(jù)預(yù)處理
1. 打亂數(shù)據(jù)
將正面文本數(shù)據(jù)與負(fù)面文本數(shù)據(jù)進行打亂
df = df.sample(frac=1) df.head()| 電視不錯,不過今年的價格比去年貴了…… | 負(fù)面 | 19 |
| 電視很清晰大品牌值得信賴 | 正面 | 12 |
| 電視不錯,沒有壞點,漏光也基本看不出來,看了下電視劇,有點拖影,網(wǎng)上換個接口就好了,暫時沒試... | 負(fù)面 | 118 |
| 喇叭太差勁,有點小卡,界面不是很友好,與泰捷盒子差太遠了,但播放效果色彩不錯,漏光較多 | 負(fù)面 | 43 |
| 好,送貨速度快,服務(wù)好。.3333333 | 正面 | 20 |
2. 分詞處理
import jiebaword_cut = lambda x: jieba.lcut(x) df['words'] = df["evaluation"].apply(word_cut) df.head() Building prefix dict from the default dictionary ... Loading model from cache C:\Users\ADMINI~1\AppData\Local\Temp\jieba.cache Loading model cost 0.442 seconds. Prefix dict has been built successfully.| 電視不錯,不過今年的價格比去年貴了…… | 負(fù)面 | 19 | [電視, 不錯, ,, 不過, 今年, 的, 價格比, 去年, 貴, 了, …, …] |
| 電視很清晰大品牌值得信賴 | 正面 | 12 | [電視, 很, 清晰, 大, 品牌, 值得, 信賴] |
| 電視不錯,沒有壞點,漏光也基本看不出來,看了下電視劇,有點拖影,網(wǎng)上換個接口就好了,暫時沒試... | 負(fù)面 | 118 | [電視, 不錯, ,, 沒有, 壞點, ,, 漏光, 也, 基本, 看不出來, ,, 看, ... |
| 喇叭太差勁,有點小卡,界面不是很友好,與泰捷盒子差太遠了,但播放效果色彩不錯,漏光較多 | 負(fù)面 | 43 | [喇叭, 太, 差勁, ,, 有點, 小卡, ,, 界面, 不是, 很, 友好, ,, 與,... |
| 好,送貨速度快,服務(wù)好。.3333333 | 正面 | 20 | [好, ,, 送貨, 速度, 快, ,, 服務(wù), 好, 。, ., 3333333] |
3. 去除停用詞
with open("hit_stopwords.txt", "r", encoding='utf-8') as f:stopwords = f.readlines()stopwords_list = [] for each in stopwords:stopwords_list.append(each.strip('\n'))# 添加自定義停用詞 stopwords_list += ["…","去","還","西","一件","月","年",".","都"]def remove_stopwords(ls): # 去除停用詞return [word for word in ls if word not in stopwords_list]df['去除停用詞后的數(shù)據(jù)']=df["words"].apply(lambda x: remove_stopwords(x)) df["y"] = np.array([1 if i=="正面" else 0 for i in df['label']]) df.head()| 電視不錯,不過今年的價格比去年貴了…… | 負(fù)面 | 19 | [電視, 不錯, ,, 不過, 今年, 的, 價格比, 去年, 貴, 了, …, …] | [電視, 不錯, 今年, 價格比, 去年, 貴] | 0 |
| 電視很清晰大品牌值得信賴 | 正面 | 12 | [電視, 很, 清晰, 大, 品牌, 值得, 信賴] | [電視, 很, 清晰, 大, 品牌, 值得, 信賴] | 1 |
| 電視不錯,沒有壞點,漏光也基本看不出來,看了下電視劇,有點拖影,網(wǎng)上換個接口就好了,暫時沒試... | 負(fù)面 | 118 | [電視, 不錯, ,, 沒有, 壞點, ,, 漏光, 也, 基本, 看不出來, ,, 看, ... | [電視, 不錯, 沒有, 壞點, 漏光, 基本, 看不出來, 看, 下, 電視劇, 有點, ... | 0 |
| 喇叭太差勁,有點小卡,界面不是很友好,與泰捷盒子差太遠了,但播放效果色彩不錯,漏光較多 | 負(fù)面 | 43 | [喇叭, 太, 差勁, ,, 有點, 小卡, ,, 界面, 不是, 很, 友好, ,, 與,... | [喇叭, 太, 差勁, 有點, 小卡, 界面, 不是, 很, 友好, 泰捷, 盒子, 差太遠... | 0 |
| 好,送貨速度快,服務(wù)好。.3333333 | 正面 | 20 | [好, ,, 送貨, 速度, 快, ,, 服務(wù), 好, 。, ., 3333333] | [好, 送貨, 速度, 快, 服務(wù), 好, 3333333] | 1 |
4. Word2vec處理
Word2vec是一個用來產(chǎn)生詞向量的模型。是一個將單詞轉(zhuǎn)換成向量形式的工具。 通過轉(zhuǎn)換,可以把對文本內(nèi)容的處理簡化為向量空間中的向量運算,計算出向量空間上的相似度,來表示文本語義上的相似度。
from gensim.models.word2vec import Word2Vecx = df["去除停用詞后的數(shù)據(jù)"]# 訓(xùn)練 Word2Vec 淺層神經(jīng)網(wǎng)絡(luò)模型 w2v = Word2Vec(vector_size=300, #是指特征向量的維度,默認(rèn)為100。min_count=10) #可以對字典做截斷. 詞頻少于min_count次數(shù)的單詞會被丟棄掉, 默認(rèn)值為5。 w2v.build_vocab(x) w2v.train(x, total_examples=w2v.corpus_count, epochs=20) # 保存 Word2Vec 模型及詞向量 w2v.save('w2v_model.pkl')# 將文本轉(zhuǎn)化為向量 def average_vec(text):vec = np.zeros(300).reshape((1, 300))for word in text:try:vec += w2v.wv[word].reshape((1, 300))except KeyError:continuereturn vec# 將詞向量保存為 Ndarray x_vec = np.concatenate([average_vec(z) for z in x]) y = df['y']5. 劃分訓(xùn)練集與測試集
from sklearn.model_selection import train_test_splitX_train,X_test,y_train,y_test = train_test_split(x_vec,y,test_size=0.2) from keras.models import Sequential from keras.layers import Dense,LSTM,Bidirectional,Embedding import tensorflow as tf#定義模型 model = Sequential() model.add(Embedding(100000, 100)) model.add(LSTM(100, dropout=0.2, recurrent_dropout=0.2)) model.add(Dense(1, activation='sigmoid'))METRICS = [tf.keras.metrics.TruePositives(name='tp'),tf.keras.metrics.FalsePositives(name='fp'),tf.keras.metrics.TrueNegatives(name='tn'),tf.keras.metrics.FalseNegatives(name='fn'), tf.keras.metrics.BinaryAccuracy(name='accuracy'), # 注意需要根據(jù)loss改變tf.keras.metrics.Precision(name='precision'),tf.keras.metrics.Recall(name='recall'),tf.keras.metrics.AUC(name='auc'),tf.keras.metrics.AUC(name='prc', curve='PR'), # precision-recall curve ]model.compile(loss='binary_crossentropy', optimizer='adam', metrics=METRICS)model.summary() WARNING:tensorflow:Layer lstm will not use cuDNN kernels since it doesn't meet the criteria. It will use a generic GPU kernel as fallback when running on GPU. Model: "sequential" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= embedding (Embedding) (None, None, 100) 10000000 _________________________________________________________________ lstm (LSTM) (None, 100) 80400 _________________________________________________________________ dense (Dense) (None, 1) 101 ================================================================= Total params: 10,080,501 Trainable params: 10,080,501 Non-trainable params: 0 _________________________________________________________________ epochs = 30 batch_size = 64history = model.fit(X_train, y_train,epochs=epochs,batch_size=batch_size,validation_split=0.2) Epoch 1/30 43/43 [==============================] - 40s 879ms/step - loss: 0.6343 - tp: 691.0000 - fp: 397.0000 - tn: 1132.0000 - fn: 520.0000 - accuracy: 0.6653 - precision: 0.6351 - recall: 0.5706 - auc: 0.6972 - prc: 0.6335 - val_loss: 0.5641 - val_tp: 194.0000 - val_fp: 76.0000 - val_tn: 304.0000 - val_fn: 112.0000 - val_accuracy: 0.7259 - val_precision: 0.7185 - val_recall: 0.6340 - val_auc: 0.7814 - val_prc: 0.7354 ...... Epoch 29/30 43/43 [==============================] - 37s 869ms/step - loss: 0.4196 - tp: 985.0000 - fp: 279.0000 - tn: 1250.0000 - fn: 226.0000 - accuracy: 0.8157 - precision: 0.7793 - recall: 0.8134 - auc: 0.8859 - prc: 0.8316 - val_loss: 0.4754 - val_tp: 244.0000 - val_fp: 74.0000 - val_tn: 306.0000 - val_fn: 62.0000 - val_accuracy: 0.8017 - val_precision: 0.7673 - val_recall: 0.7974 - val_auc: 0.8592 - val_prc: 0.8097 Epoch 30/30 43/43 [==============================] - 37s 855ms/step - loss: 0.4189 - tp: 992.0000 - fp: 301.0000 - tn: 1228.0000 - fn: 219.0000 - accuracy: 0.8102 - precision: 0.7672 - recall: 0.8192 - auc: 0.8852 - prc: 0.8336 - val_loss: 0.4716 - val_tp: 247.0000 - val_fp: 73.0000 - val_tn: 307.0000 - val_fn: 59.0000 - val_accuracy: 0.8076 - val_precision: 0.7719 - val_recall: 0.8072 - val_auc: 0.8589 - val_prc: 0.8040三、結(jié)果分析
import matplotlib as mpl mpl.rcParams['figure.figsize'] = (16, 8) colors = plt.rcParams['axes.prop_cycle'].by_key()['color']def plot_metrics(history):metrics = ['accuracy','loss', 'prc', 'precision', 'recall']for n, metric in enumerate(metrics):name = metric.replace("_"," ").capitalize()plt.subplot(2,3,n+1)plt.plot(history.epoch, history.history[metric], color=colors[2], label='Train')plt.plot(history.epoch, history.history['val_'+metric],color=colors[1], linestyle="--", label='Val')plt.xlabel('Epoch',fontsize=14)plt.ylabel(name,fontsize=14)plt.legend()plot_metrics(history)四、情感預(yù)測
# 讀取 Word2Vec 并對新輸入進行詞向量計算 def average_vec(words):# 讀取 Word2Vec 模型w2v = Word2Vec.load('w2v_model.pkl')vec = np.zeros(300).reshape((1, 300))for word in words:try:vec += w2v.wv[word].reshape((1, 300))except KeyError:continuereturn vec# 對電影評論進行情感判斷 def model_predict(string):# 對評論分詞words = jieba.lcut(str(string))words_vec = average_vec(words)# 讀取支持向量機模型# model = joblib.load('svm_model.pkl')result = np.argmax(model.predict(words_vec))# 實時返回積極或消極結(jié)果if int(result) == 1:# print(string, '[積極]')return "積極"else:# print(string, '[消極]')return "消極"comment_sentiment = []# 用10條數(shù)據(jù)做測試 for index, row in df.iloc[:10].iterrows():print(row["evaluation"],end=" | ")result = model_predict(row["去除停用詞后的數(shù)據(jù)"])comment_sentiment.append(result)print(result)#將情緒結(jié)果與原數(shù)據(jù)合并為新數(shù)據(jù) merged = pd.concat([df, pd.Series(comment_sentiment, name='用戶情緒')], axis=1) # 儲存文件 pd.DataFrame.to_csv(merged,'comment_sentiment.csv',encoding="utf-8-sig") print('done.') 電視不錯,不過今年的價格比去年貴了…… | 消極 電視很清晰大品牌值得信賴 | 消極 電視不錯,沒有壞點,漏光也基本看不出來,看了下電視劇,有點拖影,網(wǎng)上換個接口就好了,暫時沒試。京東的預(yù)約客服真的要給差評,沒經(jīng)過我同意擅自把送貨時間改到星期五,害送貨大哥白跑趟。這里要給送貨大哥好評,30幾度的天氣,大中午把電視扛到5樓 | 消極 喇叭太差勁,有點小卡,界面不是很友好,與泰捷盒子差太遠了,但播放效果色彩不錯,漏光較多 | 消極 好,送貨速度快,服務(wù)好。.3333333 | 消極 買的第一臺微鯨電視 感覺很不錯 系統(tǒng)很流暢 清晰度也可以 就是個人感覺遙控的時候會有短暫的延遲 外觀各方面還是感覺挺好的 這個價位性價比還可以 | 消極 6.18買的,活動力度大,畫面感有待提高,目前沒有質(zhì)量問題,待觀察 | 消極 挺好的,看久了下面底部很熱,售后安裝220元,被兜售一個HIDMI高清線99元,還有58元的有線電視線,一共花了快400塊錢,有點被售后忽悠了,后來網(wǎng)上一看兩根線最多40快!線上給你優(yōu)惠,線下想法搞你! | 消極 挺好的 就是開發(fā)票太慢了 催了好久到現(xiàn)在還沒到呢 | 消極 圖電視劇的尺寸大性價比較高,最主要的就是搞活動的時候價格也不是太高啦 | 消極 done.總結(jié)
以上是生活随笔為你收集整理的基于LSTM电商评论情感分析-多评价指标可视化版(内附源码)【自然语言处理NLP-100例】的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 新手入门深度学习 | 卷积神经网络是什么
- 下一篇: Matplotlib实例教程 | 配色表