使用kears分析中文酒店評論(肯定和否定)揩抡,基于CNN和RNN

下載清華大學的賓館評論數(shù)據(jù)集

from tensorflow import keras
import os
# 自動解壓笼踩,新建review_sentiment目錄
path = keras.utils.get_file('review_sentiment.v1.tgz', origin='http://nlp.csai.tsinghua.edu.cn/~lj/review_sentiment.v1.tgz',cache_subdir='review_sentiment',extract='true')

pre_path=os.path.split(path)[0] 
# 得到上級目錄
print(pre_path)
# 打印文件結構
print(os.listdir(pre_path))
/root/.keras/review_sentiment
['review_sentiment.v1.tgz', 'train2', 'test2', 'train2.list', 'train2.rlabelclass', 'test2.list', 'test2.rlabelclass', 'readme.txt', 'readme.cn.txt']

處理數(shù)據(jù)文本文件

import os
import numpy as np
thu1 = thulac.thulac(seg_only=True)

max_lenth=0
def get_data(dir,label_file):
    x=[]
    y=[]
    dir=os.path.join(pre_path,dir)
    label_file=os.path.join(pre_path,label_file)

    dic={}# 文件名所對應的label 詞典
    f = open(label_file,'r+')
    for line in f:
        (key,value) = line.strip().split(' ')
        dic[key] = value
    f.close()
    
    for fname in os.listdir(dir):
        if fname[-4:]=='.txt':
            try:
                with open(os.path.join(dir,fname), encoding='gbk') as f:
                    text = thu1.cut(f.read())  #因為中文和英文有區(qū)別莫矗,需要進行分詞咽弦,我使用的是清華大學的thu1烛占,可以使用pip install thu1 安裝
                    text=' '.join(np.asarray(text)[:,0:1].reshape(-1))
                    x.append(text)
                    if dic[fname]=='+1':
                        y.append(1)
                    else:
                        y.append(0)
                    f.close()
            except:
                print(fname,'有問題')
    return x,y
    
train_x,train_y=get_data('train2','train2.rlabelclass')
test_x,test_y=get_data('test2','test2.rlabelclass')  
train_y=np.asarray(train_y)
test_y=np.asarray(test_y)
print('len(test_x)',len(test_x))
print('len(train_x)',len(train_x))


            
Model loaded succeed
56958_helen1970_2005-7-22_1.3.txt 有問題
51254_31801272_2006-9-15_1.5.txt 有問題
78674_hupu1128_2005-6-2_1.5.txt 有問題
23733_clcsandy_2006-10-7_1.8.txt 有問題
len(test_x) 4000
len(train_x) 11996

查看分詞過的數(shù)據(jù)

print(train_x[100],train_y[100])
print(train_x[6000],train_y[6000])

我 覺得 大觀園 挺 好 的 胎挎, 首先 是 房間 好 , 床 挺 舒適 的 忆家。 最 好 的 就 是 可以 免費 游園 犹菇, 還 能 免費 游泳 , 不 過 游泳 時 一定 要 帶 浴帽 不 太 符合 中國 國情 芽卿。 
                                   1
我 帶 外賓 入 住 揭芍, 外賓 說 臟 , 有 女人 頭發(fā) 卸例, 噴頭 掉 地上 等 称杨, 換 到 西苑飯店 
                                   0

將數(shù)據(jù)轉成向量

from keras.preprocessing.text import Tokenizer
from keras.preprocessing.sequence import pad_sequences
maxlen=200# 200漢字后截斷
max_words=5000 # 只考慮前10000個漢字

tokenizer=Tokenizer(num_words=max_words,filters='肌毅,!姑原。!"#$%&()*+,-./:;<=>?@[\]^_`{|}~\t\n')
tokenizer.fit_on_texts(train_x)
train_sequences=tokenizer.texts_to_sequences(train_x)
test_sequences=tokenizer.texts_to_sequences(test_x)

train_xx=pad_sequences(train_sequences,maxlen=200)
test_xx=pad_sequences(test_sequences,maxlen=200)

查看向量數(shù)據(jù)

print(train_xx[100],train_y[100])
print(train_xx[6000],train_y[6000])

[   0    0    0    0    0    0    0    0    0    0    0    0    0    0
    0    0    0    0    0    0    0    0    0    0    0    0    0    0
    0    0    0    0    0    0    0    0    0    0    0    0    0    0
    0    0    0    0    0    0    0    0    0    0    0    0    0    0
    0    0    0    0    0    0    0    0    0    0    0    0    0    0
    0    0    0    0    0    0    0    0    0    0    0    0    0    0
    0    0    0    0    0    0    0    0    0    0    0    0    0    0
    0    0    0    0    0    0    0    0    0    0    0    0    0    0
    0    0    0    0    0    0    0    0    0    0    0    0    0    0
    0    0    0    0    0    0    0    0    0    0    0    0    0    0
    0    0    0    0    0    0    0    0    0    0    0    0    0    0
    0    0    0    0    0    0    0    0    0    0    5  195  255   10
    1  740    3    8   10  102  255  283    1   56   10    1   15    3
   42  134   18   48  134 1813    2   37 1813   85  244   22  272 4587
    2   34 1028  698] 1
[   0    0    0    0    0    0    0    0    0    0    0    0    0    0
    0    0    0    0    0    0    0    0    0    0    0    0    0    0
    0    0    0    0    0    0    0    0    0    0    0    0    0    0
    0    0    0    0    0    0    0    0    0    0    0    0    0    0
    0    0    0    0    0    0    0    0    0    0    0    0    0    0
    0    0    0    0    0    0    0    0    0    0    0    0    0    0
    0    0    0    0    0    0    0    0    0    0    0    0    0    0
    0    0    0    0    0    0    0    0    0    0    0    0    0    0
    0    0    0    0    0    0    0    0    0    0    0    0    0    0
    0    0    0    0    0    0    0    0    0    0    0    0    0    0
    0    0    0    0    0    0    0    0    0    0    0    0    0    0
    0    0    0    0    0    0    0    0    0    0    0    0    0    0
    0    0    0    0    0    0    0    0    0    0    0    0    0    0
    0    5  272 1385   53    9 1385   26  214   14 1838 1325 2438  445
 1170  125  138   20] 0

創(chuàng)建模型(使用CNN和RNN)

from tensorflow.python.keras import Sequential
from tensorflow.python.keras.preprocessing import sequence
from tensorflow.keras.datasets import imdb
from tensorflow.keras import layers
from tensorflow import keras
from tensorflow.python.keras.utils import multi_gpu_model

model = Sequential([
   layers.Embedding(5000, 128, input_length=maxlen),
    layers.Conv1D(32, 7, activation='relu'),
    layers.MaxPool1D(5),
    layers.Conv1D(32, 7, activation='relu'),
    layers.GRU(32,dropout=0.1,recurrent_dropout=0.5),
    layers.Dense(1, activation='sigmoid')
])
model.summary()

_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
embedding_39 (Embedding)     (None, 200, 128)          640000    
_________________________________________________________________
conv1d_51 (Conv1D)           (None, 194, 32)           28704     
_________________________________________________________________
max_pooling1d_25 (MaxPooling (None, 38, 32)            0         
_________________________________________________________________
conv1d_52 (Conv1D)           (None, 32, 32)            7200      
_________________________________________________________________
gru_14 (GRU)                 (None, 32)                6240      
_________________________________________________________________
dense_41 (Dense)             (None, 1)                 33        
=================================================================
Total params: 682,177
Trainable params: 682,177
Non-trainable params: 0
_________________________________________________________________

訓練模型


model.compile(optimizer=keras.optimizers.Adam(), loss='binary_crossentropy', metrics=['acc'])
history = model.fit(train_xx, train_y, epochs=20, batch_size=128, validation_data=(test_xx,test_y),shuffle=True)


/usr/lib/python3.6/site-packages/tensorflow/python/ops/gradients_impl.py:100: UserWarning: Converting sparse IndexedSlices to a dense Tensor of unknown shape. This may consume a large amount of memory.
  "Converting sparse IndexedSlices to a dense Tensor of unknown shape. "


Train on 11996 samples, validate on 4000 samples
Epoch 1/20
11996/11996 [==============================] - 10s 835us/step - loss: 0.6656 - acc: 0.6062 - val_loss: 0.6899 - val_acc: 0.5767
Epoch 2/20
11996/11996 [==============================] - 5s 384us/step - loss: 0.5150 - acc: 0.7519 - val_loss: 0.4344 - val_acc: 0.8015
Epoch 3/20
11996/11996 [==============================] - 5s 383us/step - loss: 0.2847 - acc: 0.8781 - val_loss: 0.3883 - val_acc: 0.8282
Epoch 4/20
11996/11996 [==============================] - 5s 383us/step - loss: 0.1947 - acc: 0.9231 - val_loss: 0.4066 - val_acc: 0.8323
Epoch 5/20
11996/11996 [==============================] - 5s 384us/step - loss: 0.1442 - acc: 0.9458 - val_loss: 0.3524 - val_acc: 0.8622
Epoch 6/20
11996/11996 [==============================] - 5s 384us/step - loss: 0.1225 - acc: 0.9520 - val_loss: 0.3714 - val_acc: 0.8587
Epoch 7/20
11996/11996 [==============================] - 5s 384us/step - loss: 0.1048 - acc: 0.9592 - val_loss: 0.3849 - val_acc: 0.8635
Epoch 8/20
11996/11996 [==============================] - 5s 384us/step - loss: 0.0895 - acc: 0.9648 - val_loss: 0.4006 - val_acc: 0.8628
Epoch 9/20
11996/11996 [==============================] - 5s 384us/step - loss: 0.0738 - acc: 0.9702 - val_loss: 0.4215 - val_acc: 0.8645
Epoch 10/20
11996/11996 [==============================] - 5s 384us/step - loss: 0.0567 - acc: 0.9784 - val_loss: 0.4656 - val_acc: 0.8572
Epoch 11/20
11996/11996 [==============================] - 5s 383us/step - loss: 0.0487 - acc: 0.9802 - val_loss: 0.5072 - val_acc: 0.8605
Epoch 12/20
11996/11996 [==============================] - 5s 383us/step - loss: 0.1366 - acc: 0.9488 - val_loss: 0.4496 - val_acc: 0.8602
Epoch 13/20
11996/11996 [==============================] - 5s 385us/step - loss: 0.0462 - acc: 0.9813 - val_loss: 0.5016 - val_acc: 0.8587
Epoch 14/20
11996/11996 [==============================] - 5s 383us/step - loss: 0.0369 - acc: 0.9837 - val_loss: 0.5263 - val_acc: 0.8583
Epoch 15/20
11996/11996 [==============================] - 5s 383us/step - loss: 0.0326 - acc: 0.9852 - val_loss: 0.5504 - val_acc: 0.8622
Epoch 16/20
11996/11996 [==============================] - 5s 384us/step - loss: 0.0304 - acc: 0.9864 - val_loss: 0.5893 - val_acc: 0.8568
Epoch 17/20
11996/11996 [==============================] - 5s 384us/step - loss: 0.0401 - acc: 0.9810 - val_loss: 0.6242 - val_acc: 0.8480
Epoch 18/20
11996/11996 [==============================] - 5s 384us/step - loss: 0.0289 - acc: 0.9861 - val_loss: 0.6144 - val_acc: 0.8558
Epoch 19/20
11996/11996 [==============================] - 5s 383us/step - loss: 0.0266 - acc: 0.9872 - val_loss: 0.6810 - val_acc: 0.8525
Epoch 20/20
11996/11996 [==============================] - 5s 383us/step - loss: 0.0241 - acc: 0.9882 - val_loss: 0.6731 - val_acc: 0.8522

查看錯誤的預測

predict_y=np.max(model.predict_classes(test_xx),axis=1)


result=np.equal(predict_y,test_y)

index_wrong=np.where(result==False)

wrong_text=np.asarray(test_x)[index_wrong]
wrong_predict_y=predict_y[index_wrong]
wrong_test_y=test_y[index_wrong]
dict_label={0:'否定',1:'肯定'}

for wt,wpy,wty in zip(wrong_text[0:10],wrong_predict_y[0:10],wrong_test_y[0:10]):
    print(wt.strip().replace(' ',''),'\t\t預測:'+dict_label[wpy],'實際:'+dict_label[wty])


什么都好悬而,就是凌晨5店多有騷擾電話吃不消。希望酒店加強管理锭汛。給客人一個清靜的休息環(huán)境笨奠。順便提一下,健身房一流唤殴!         預測:否定 實際:肯定
有一點意見大堂總是有飯菜味道,五星級酒店不應該.        預測:否定 實際:肯定
位置絕佳,房間再精雕細刻一些就更好了,大小合適,床也夠大.       預測:否定 實際:肯定
如果所有員工都面帶微笑會更加理想.       預測:否定 實際:肯定
房間還行艰躺,價格一般,早餐不錯眨八,希望提高服務質量         預測:否定 實際:肯定
酒店不錯,就是設施陳舊了點,服務還可以,房間很大~~      預測:否定 實際:肯定
世界各地喜來登也住了不少腺兴,這所座落在蘇州的具有園林特色的酒店讓人耳目一新。酒店大堂里現(xiàn)場民樂show很有特色廉侧,唯有的兩個小缺憾:1.挺有名氣的自助餐廳吃的那叫啥?!完全和昂貴的價格不符页响。2.房間內設備略顯陳舊。
BTW:前臺周小姐是我所入住過的世界各地所有酒店里態(tài)度最好段誊,笑容最甜美的服務人員闰蚕。       預測:否定 實際:肯定
迎賓樓好像重新裝修過了,環(huán)境不錯连舍。房間居然還有一臺電腦没陡,只不過屏幕是CRT的,不是液晶索赏,相對瘦型的主機來講盼玄,好像頭大身子小的大頭娃娃。網(wǎng)絡速度還算是不錯的潜腻,只是安裝的軟件全都太老了埃儿,無法直接使用,而且機器采用無盤工作站的方式融涣,安裝的是WINME操作系統(tǒng)童番,不算太好用,打游戲或者做做字處理工作威鹿,配合U盤還算不錯了剃斧。至于酒店各部門服務人員的態(tài)度還算不錯,夠5星水準了忽你。      預測:否定 實際:肯定
可能是溫州最好的酒店幼东。服務比較規(guī)范。中餐廳不錯。        預測:否定 實際:肯定
前臺小姑娘服務很好筋粗,會和客人小聊幾句,不刻板很人性化炸渡。
行李員服務到位娜亿,解釋送地圖很快捷,金鑰匙水平蚌堵;但是一次坐出租車晚上回來买决,司機停車不當上了逆行,一個門僮小伙子直接用力敲擊前窗吼畏,讓人惱火督赤;客人坐在里面,不尊重出租車也要尊重客人泻蚊。
裝潢顯舊了(不知“2005裝修”在哪里)躲舌,電梯里面干凈就是視覺亂七八糟。房間設施還可以性雄。
早餐92元没卸,現(xiàn)優(yōu)惠60元,基本可以秒旋。
位置優(yōu)勢明顯约计,海景、情侶大道迁筛。價格可以接收煤蚌。
補充點評2007年1月11日:補充:浴室衛(wèi)生紙架太靠后,取用不方便细卧。      預測:否定 實際:肯定

后記

  1. 使用一維的卷積很快尉桩,筆者顯卡gtx 750ti,運行起來也很快速
  2. 預測錯誤的數(shù)據(jù)贪庙,觀察得知大部分魄健,是因為評論中說了不好的,也說的好的插勤,其實這些分類可以歸為新的分類
  3. 如果不使用分詞工具分詞話沽瘦,正確率不會很高,先分詞农尖,然后用空格分隔析恋,這樣就和英文單詞一樣了,就可以參考imdb數(shù)據(jù)了
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末盛卡,一起剝皮案震驚了整個濱河市助隧,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖并村,帶你破解...
    沈念sama閱讀 211,884評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件巍实,死亡現(xiàn)場離奇詭異,居然都是意外死亡哩牍,警方通過查閱死者的電腦和手機棚潦,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,347評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來膝昆,“玉大人丸边,你說我怎么就攤上這事〖苑酰” “怎么了妹窖?”我有些...
    開封第一講書人閱讀 157,435評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長收叶。 經(jīng)常有香客問我骄呼,道長,這世上最難降的妖魔是什么判没? 我笑而不...
    開封第一講書人閱讀 56,509評論 1 284
  • 正文 為了忘掉前任谒麦,我火速辦了婚禮,結果婚禮上哆致,老公的妹妹穿的比我還像新娘绕德。我一直安慰自己,他們只是感情好摊阀,可當我...
    茶點故事閱讀 65,611評論 6 386
  • 文/花漫 我一把揭開白布耻蛇。 她就那樣靜靜地躺著,像睡著了一般胞此。 火紅的嫁衣襯著肌膚如雪臣咖。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,837評論 1 290
  • 那天漱牵,我揣著相機與錄音夺蛇,去河邊找鬼。 笑死酣胀,一個胖子當著我的面吹牛刁赦,可吹牛的內容都是我干的。 我是一名探鬼主播闻镶,決...
    沈念sama閱讀 38,987評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼甚脉,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了铆农?” 一聲冷哼從身側響起牺氨,我...
    開封第一講書人閱讀 37,730評論 0 267
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后猴凹,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體夷狰,經(jīng)...
    沈念sama閱讀 44,194評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,525評論 2 327
  • 正文 我和宋清朗相戀三年郊霎,在試婚紗的時候發(fā)現(xiàn)自己被綠了沼头。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,664評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡歹篓,死狀恐怖瘫证,靈堂內的尸體忽然破棺而出揉阎,到底是詐尸還是另有隱情庄撮,我是刑警寧澤,帶...
    沈念sama閱讀 34,334評論 4 330
  • 正文 年R本政府宣布毙籽,位于F島的核電站洞斯,受9級特大地震影響,放射性物質發(fā)生泄漏坑赡。R本人自食惡果不足惜烙如,卻給世界環(huán)境...
    茶點故事閱讀 39,944評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望毅否。 院中可真熱鬧亚铁,春花似錦、人聲如沸螟加。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,764評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽捆探。三九已至然爆,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間黍图,已是汗流浹背曾雕。 一陣腳步聲響...
    開封第一講書人閱讀 31,997評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留助被,地道東北人剖张。 一個月前我還...
    沈念sama閱讀 46,389評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像揩环,于是被迫代替她去往敵國和親修械。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,554評論 2 349

推薦閱讀更多精彩內容