Keras文本数据预处理范例——IMDB影评情感分类

推荐算法智能内容增长营销

本文将以IMDB电影评论数据集为范例,介绍Keras对文本数据预处理并喂入神经网络模型的方法。

IMDB数据集的目标是根据电影评论的文本内容预测评论的情感标签。训练集有20000条电影评论文本,测试集有5000条电影评论文本,其中正面评论和负面评论都各占一半。

文本数据预处理主要包括中文切词(本示例不涉及),构建词典,序列填充,定义数据管道等步骤。让我们出发吧!

一,准备数据

1,获取数据

在公众号后台回复关键字:imdb,可以获取IMDB数据集的下载链接。数据大小约为13M,解压后约为31M。

数据集结构如下所示。

picture.image

直观感受一下文本内容。

picture.image

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 = 20000 #训练集样本数量  
test_samples = 5000 #测试集样本数量  
  
max_words = 10000  # 保留词频最高的前10000个词  
maxlen = 500       # 每个样本文本内容最多保留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[0:maxlen]  
            pbar.update(1)  
            yield text  
  
texts = texts_gen()  
tokenizer = Tokenizer(num_words=max_words)  
tokenizer.fit_on_texts(texts)  
  

      

看一下我们生成的词典。

picture.image

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)  
  

      

picture.image

4,定义管道

通过继承keras.utils.Sequence类,我们可以构建像ImageDataGenerator那样能够并行读取数据的生成器管道。尽管下面的代码看起来有些长,但通常只有__data_generation方法需要被修改。


          
# 定义Sequence数据管道, 可以多线程读数据  
  
import keras  
import numpy as np  
from keras.preprocessing.sequence import pad_sequences  
  
batch_size = 64  
  
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+1)*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')[0]) 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)  
  

      

picture.image

二,构建模型

为了将文本token后的整数序列用神经网络进行处理,我们在第一层使用了Embedding层,Embedding层从数学上等效为将输入数据进行onehot编码后的一个全连接层,在形式上以查表方式实现以提升效率。


          
from keras import models,layers  
from keras import backend as K  
K.clear_session()  
  
embedding_dim = 4  
  
model = models.Sequential()  
model.add(layers.Embedding(max_words, embedding_dim, input_length=maxlen))  
model.add(layers.Flatten())  
model.add(layers.Dense(32,activation = 'relu'))  
model.add(layers.Dense(1, activation = 'sigmoid'))  
model.summary()  
  
model.compile(optimizer='adam',  
              loss='binary\_crossentropy',  
              metrics=['acc'])  
  

      

picture.image

三,训练模型


          
epoch_num = 5  
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=1,  
                         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(1, len(acc) + 1)  
dfhistory  = pd.DataFrame({'epoch':epochs,'train\_loss':loss,'test\_loss':val_loss,  
                  'train\_acc':acc,'test\_acc':val_acc})  
  
print(dfhistory)  

      

picture.image

五,使用模型

picture.image

六,保存模型


          
model.save('imdb\_model.h5')  
  

      

推荐阅读:

用Keras从零开始6步骤训练神经网络

Keras结构化数据预处理范例——Titanic生存预测

Keras图像数据预处理范例——Cifar2图片分类

picture.image

0
0
0
0
关于作者
关于作者

文章

0

获赞

0

收藏

0

相关资源
基于 ByteHouse 引擎的增强型数据导入技术实践
ByteHouse 基于自研 HaMergeTree,构建增强型物化 MySQL、HaKafka 引擎,实现数据快速集成,加速业务数据分析性能与效率,本次 talk 主要介绍物化 MySQL 与 HaKafka 数据导入方案和业务实践。
相关产品
评论
未登录
看完啦,登录分享一下感受吧~
暂无评论