Tensorflow2.0學習(五) — Keras基礎應用(IMDb電影集情感分析)

今天這一節內容是關於Keras應用分析的最後一節,在熟悉了Keras的基礎知識之後,下面幾節我們就可以正式接觸Tensorflow2.0。根據博主多處查閱,最終還是發現Tensorflow的官方教程好一點,但是官方的代碼很多沒有註釋,不方便初學者理解,因此下幾節的內容會主要會針對Tensorflow2.0的官方文檔的代碼進行講解和運行,在之後當我們對Tensorflow2.0有了一定了解,我會詳細的用Tensorflow2.0帶大家搭建許多經典模型比如Alexnet、Googlenet和U-Net等等,對一些經典論文進行復現,並分享我曾經做的一些小項目的代碼。如果對這些內容有不大清楚的朋友們,可以觀看前面幾節的代碼,希望大家多多支持。

其它話不多說,先分享這節的內容。我們將在這節分別構建MLP對IMDb電影集做情感分析。IMDb全稱爲網絡電影數據庫,裏面包含各種電影數據,我們這次主要的任務是從IMDb中摘取影評文字(一共50000項),裏面分別有25000項正面評價及25000項負面評價,我們將用Keras搭建模型進行訓練,預測出新影評文字是正面評價還是負面的評價。

一.IMDb數據集的加載和讀取

1.導入相關庫。其中sequence庫用於修正數據的長度,Tokenizer庫用於建立字典(後續需要將文字映射爲數字),re庫爲正則表達式處理(影評很多是爬蟲下載的,含有html標籤,可以用正則表達式去除),tarfile庫用於解壓縮下載的數據集文件。

import tensorflow as tf
from tensorflow.keras import layers
from tensorflow.keras.preprocessing import sequence   #修正數據長度
from tensorflow.keras.preprocessing.text import Tokenizer #建立字典
import urllib.request #下載遠程數據
import os #判斷文件是否存在
import tarfile #解壓縮文件
import re #正則表達式
import numpy as np

2.文件下載。和上一節一樣,我們可以用request庫進行下載,但是直接代碼運行下載可能速度很慢,大家可以把url鏈接裏的內容複製到迅雷裏下載,速度會快一些,之後把壓縮包黏貼在自己的keras數據目錄下即可。

url="http://ai.stanford.edu/~amaas/data/sentiment/aclImdb_v1.tar.gz" 
filepath = "aclImdb_v1.tar.gz"
if not os.path.isfile(filepath): #判斷數據文件是否存在,如果不存在則下載
    result = urllib.request.urlretrieve(url,filepath) #下載數據
    print("download")

3.文件解壓縮。aclImdb_v1.tar.gz裏包含的文件夾名是aclImdb,因此我們解壓縮判斷的時候是判斷aclImdb這個名字。

if not os.path.exists("aclImdb"):
    tfile = tarfile.open("aclImdb_v1.tar.gz",'r:gz') #創建壓縮包名
    result=tfile.extractall("") #進行解壓縮,提取文件

4.定義正則表達式。影評很多是爬蟲下載的,含有html標籤的代碼信息,我們需要用正則表達式去除這部分我們不需要的內容。正則表達式的語法大家可以查看下其它博客,有更詳細的介紹。

def rm_tags(text):
    re_tag = re.compile(r'<[^>]+>') #匹配HTML標籤
    return re_tag.sub('',text) #將html標籤替換爲空白值

5.定義函數,讀取文件裏的所有數據,並保存到列表裏。這裏展示一下文件夾裏面的東西,方便大家理解。因爲數據集沒有提供標籤,所以我們人爲進行創建1(正面)和0(反面)代表二分類的結果。

  

其中我們的影評內容都保存在這些txt文檔裏。

def read_files(filetype):
    path = "aclImdb/"        #數據集路徑
    file_list = []  
    positive_path = path+filetype+"/pos/"  #正面評論數據集路徑,這裏讀到的是文件名
    for i in os.listdir(positive_path):
        file_list+=[positive_path+i]       
    negative_path = path+filetype+"/neg/"  #反面評論數據集路徑,這裏讀到的是文件名
    for i in os.listdir(negative_path):
        file_list+=[negative_path+i]
    print("read:",filetype,"file_len:",len(file_list))
    all_labels=([1]*12500+[0]*12500) #人爲製作標籤,1代表正面,0代表反面
    all_labels=np.array(all_labels) #列表轉爲數組,不然無法訓練
    all_texts = []
    for i in file_list:
        with open(i,encoding='utf8') as file_input: #根據列表的文件名打開所有文件
            all_texts +=[rm_tags(" ".join(file_input.readlines()))] #逐行讀入正則化後的文件內容
    return all_labels,all_texts

6.調用該函數,製作訓練集、測試集並打印長度。

y_train,x_train = read_files("train")
y_test,x_test = read_files("test")

二.IMDb數據集的預處理

1.建立文字轉數字字典。我們都知道深度學習模型只能訓練數字數據,因此我們需要將影評文字轉化爲數字列表。那麼如何轉換?當我們要將一種語言翻譯成另一種語言時需要字典,因此文字轉數字也是一樣。我們可以使用keras的Tokenizer模塊完成這個功能。在這裏我們只選取了排序前2000名的英文單詞加入字典,因爲2000名後的單詞出現概率小,對我們的模型影響不大,當然選取多一點也是可以的。下圖即是我們影評文字中對應的出現頻率最高的2000詞字典。

token = Tokenizer(num_words=2000)
token.fit_on_texts(x_train)
print(token.word_index) #打印單詞對印的數字列表

2.將token應用在我們的數據集上,使每段話轉換爲數字。

x_train_seq = token.texts_to_sequences(x_train)
x_test_seq = token.texts_to_sequences(x_test)

3.打印其中一個影評,查看結果。

print(x_train_seq[0])

我們發現原本的一段文字已經變成了數字。

4.利用Sequence庫設置每個數據大小。大家都知道神經網絡輸入層是要求所有數據都要有固定統一大小的,但我們的影評數據大小不一,因此我們可以用這個庫對所有影評數據截長補短,長的影評截掉,短的影評補充上去,使他們大小相等。

x_train_digit = sequence.pad_sequences(x_train_seq,maxlen=100) #maxlen代表你想要的數據長度
x_test_digit = sequence.pad_sequences(x_test_seq,maxlen=100)
x_train_digit[0].shape

我們發現數據長度已經被修改到了100。

三.搭建模型

1.創建Sequential線性堆疊模型。

model = tf.keras.models.Sequential()

2.添加模型層。在這裏注意的是我們添加了一層Embedding層,這個層的名字爲嵌入層,爲什麼需要這個層呢?我們都知道我們雖然前面把文字轉化成了數字,但是它們之間卻是沒有關聯的。然而正常生活中,我們說的話很多是帶有邏輯,前後相關的,因此我們需要把文字間的聯繫考慮進去。而Embedding層的作用就是將數字映射爲多維幾何空間的向量,而向量空間有個特徵就是相似的值在空間內會比較接近,因此就可以起到一定的前後聯繫作用,增加我們模型的準確率。

#input_dim爲2000因爲我們有2000個詞字典,input_length爲100是我們的數據長度設置成了統一100
model.add(layers.Embedding(input_dim=2000,output_dim=32,input_length=100))
model.add(layers.Dropout(0.2))
model.add(layers.Flatten())
model.add(layers.Dense(units=256,activation='relu'))
model.add(layers.Dropout(0.2))
model.add(layers.Dense(units=1,activation='sigmoid'))

3.打印模型概要。

print(model.summary())

四.模型設置及訓練

1.設置模型參數。因爲是二分類任務,因此損失函數爲binary。

model.compile(optimizer='adam',loss='binary_crossentropy',metrics=['accuracy'])

2.訓練模型。

train_history = model.fit(x_train_digit,y_train,batch_size=100,epochs=10,verbose=2,validation_split=0.2)

五.模型測試及預測

1.模型測試。

scores = model.evaluate(x_test_digit,y_test,verbose=2)
print(scores[1])

2.模型預測,並將結果轉化爲一維值。

predict = model.predict_classes(x_test_digit).reshape(-1)
predict[:10] #預測前10個值

3.定義函數,顯示影評和預測結果。

sentimenDict={1:"正面的",0:"負面的"}
def display_test_sentiment(i):
    print(x_test[i])
    print("label:",sentimenDict[y_test[i]],"predict",sentimenDict[predict[i]]) #預測的數字映射成字典的值顯示

display_test_sentiment(3)

 

這是本節的所有內容,謝謝大家的支持和觀看,有疑問探討的地方歡迎留言。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章