天天看點

Keras文本資料預處理範例——IMDB影評情感分類

本文将以IMDB電影評論資料集為範例,介紹Keras對文本資料預處理并喂入神經網絡模型的方法。

IMDB資料集的目标是根據電影評論的文本内容預測評論的情感标簽。訓練集有20000條電影評論文本,測試集有5000條電影評論文本,其中正面評論和負面評論都各占一半。

文本資料預處理主要包括中文切詞(本示例不涉及),建構詞典,序列填充,定義資料管道等步驟。讓我們出發吧!

一,準備資料

1,擷取資料

在公衆号背景回複關鍵字:imdb,可以擷取IMDB資料集的下載下傳連結。資料大小約為13M,解壓後約為31M。

資料集結構如下所示。

Keras文本資料預處理範例——IMDB影評情感分類

直覺感受一下文本内容。

Keras文本資料預處理範例——IMDB影評情感分類

2,建構詞典

為了能夠将文本資料喂入模型,我們一般要建構詞典,以便将詞轉換成對應的token(即數字編碼)。

from keras.preprocessing.text import Tokenizer
from tqdm import tqdm 

# 資料集路徑
train_data_path = 'imdb_datasets/xx_train_imdb'
test_data_path = 'imdb_datasets/xx_test_imdb'

train_samples =  #訓練集樣本數量
test_samples =  #測試集樣本數量

max_words =   # 保留詞頻最高的前10000個詞
maxlen =        # 每個樣本文本内容最多保留500個詞

# 建構訓練集文本生成器
def texts_gen():
    with open(train_data_path,'r',encoding = 'utf-8') as f,\
    tqdm(total = train_samples) as pbar:      
        while True:
            text = (f.readline().rstrip('\n').split('\t')[-1])
            if not text:
                break
            if len(text) > maxlen:
                text = text[:maxlen]
            pbar.update()
            yield text

texts = texts_gen()
tokenizer = Tokenizer(num_words=max_words)
tokenizer.fit_on_texts(texts)

           

複制

看一下我們生成的詞典。

Keras文本資料預處理範例——IMDB影評情感分類

3,分割樣本

為了能夠像ImageDataGenerator那樣用資料管道多程序并行地讀取資料,我們需要将資料集按樣本分割成多個檔案。

import os

scatter_train_data_path = 'imdb_datasets/train/'
scatter_test_data_path = 'imdb_datasets/test/'

# 将資料按樣本打散到多個檔案
def scatter_data(data_file, scatter_data_path):
    if not os.path.exists(scatter_data_path):
        os.makedirs(scatter_data_path)
    for idx,line in tqdm(enumerate(open(data_file,'r',encoding = 'utf-8'))):
        with open(scatter_data_path + str(idx) + '.txt','w',
        encoding = 'utf-8') as f:
             f.write(line)

scatter_data(train_data_path,scatter_train_data_path)
scatter_data(test_data_path,scatter_test_data_path)

           

複制

Keras文本資料預處理範例——IMDB影評情感分類

4,定義管道

通過繼承keras.utils.Sequence類,我們可以建構像ImageDataGenerator那樣能夠并行讀取資料的生成器管道。盡管下面的代碼看起來有些長,但通常隻有__data_generation方法需要被修改。

# 定義Sequence資料管道, 可以多線程讀資料

import keras
import numpy as np
from keras.preprocessing.sequence import pad_sequences

batch_size = 

class DataGenerator(keras.utils.Sequence):

    def __init__(self,n_samples,data_path,batch_size=batch_size,shuffle=True):
        self.data_path = data_path
        self.n_samples = n_samples
        self.batch_size = batch_size
        self.shuffle = shuffle
        self.on_epoch_end()

    def __len__(self):
        return int(np.ceil(self.n_samples/self.batch_size))

    def __getitem__(self, index):
        # Generate indexes of the batch
        batch_indexes = self.indexes[index*self.batch_size:(index+)*self.batch_size]
        # Generate data
        datas, labels = self.__data_generation(batch_indexes)
        return datas, labels

    def on_epoch_end(self):
        self.indexes = np.arange(self.n_samples)
        if self.shuffle == True:
            np.random.shuffle(self.indexes)

    def __read_file(self,file_name):
        with open(file_name,encoding = 'utf-8') as f:
            line = f.readline()
        return line

    def __data_generation(self, batch_indexes):
        lines = [self.__read_file(self.data_path + str(i) + '.txt') for i in batch_indexes]
        labels = np.array([int(line.strip().split('\t')[]) for line in lines])
        texts = [line.strip().split('\t')[-1] for line in lines]
        sequences = tokenizer.texts_to_sequences(texts)
        datas = pad_sequences(sequences,maxlen)

        return datas,labels


train_gen = DataGenerator(train_samples,scatter_train_data_path)
test_gen = DataGenerator(test_samples,scatter_test_data_path)

           

複制

Keras文本資料預處理範例——IMDB影評情感分類

二,構模組化型

為了将文本token後的整數序列用神經網絡進行處理,我們在第一層使用了Embedding層,Embedding層從數學上等效為将輸入資料進行onehot編碼後的一個全連接配接層,在形式上以查表方式實作以提升效率。

from keras import models,layers
from keras import backend as K
K.clear_session()

embedding_dim = 

model = models.Sequential()
model.add(layers.Embedding(max_words, embedding_dim, input_length=maxlen))
model.add(layers.Flatten())
model.add(layers.Dense(,activation = 'relu'))
model.add(layers.Dense(, activation = 'sigmoid'))
model.summary()

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

           

複制

Keras文本資料預處理範例——IMDB影評情感分類

三,訓練模型

epoch_num = 
steps_per_epoch = int(np.ceil(train_samples/batch_size))
validation_steps = int(np.ceil(test_samples/batch_size))

history = model.fit_generator(train_gen,
                         steps_per_epoch = steps_per_epoch,
                         epochs = epoch_num,
                         validation_data= test_gen,
                         validation_steps = validation_steps,
                         workers=,
                         use_multiprocessing=False #linux上可使用多程序讀取資料
                         )
           

複制

四,評估模型

import os
import pandas as pd

# 儲存得分
acc = history.history['acc']
val_acc = history.history['val_acc']
loss = history.history['loss']
val_loss = history.history['val_loss']

epochs = range(, len(acc) + )
dfhistory  = pd.DataFrame({'epoch':epochs,'train_loss':loss,'test_loss':val_loss,
                  'train_acc':acc,'test_acc':val_acc})

print(dfhistory)
           

複制

Keras文本資料預處理範例——IMDB影評情感分類

五,使用模型

Keras文本資料預處理範例——IMDB影評情感分類

六,儲存模型

model.save('imdb_model.h5')           

複制