前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Keras文本数据预处理范例——IMDB影评情感分类

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

作者头像
lyhue1991
发布2020-07-20 14:12:08
1.1K0
发布2020-07-20 14:12:08
举报

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

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

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

一,准备数据

1,获取数据

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

数据集结构如下所示。

直观感受一下文本内容。

2,构建词典

为了能够将文本数据喂入模型,我们一般要构建词典,以便将词转换成对应的token(即数字编码)。

代码语言:javascript
复制
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)

看一下我们生成的词典。

3,分割样本

为了能够像ImageDataGenerator那样用数据管道多进程并行地读取数据,我们需要将数据集按样本分割成多个文件。

代码语言:javascript
复制
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)

4,定义管道

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

代码语言:javascript
复制
# 定义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)

二,构建模型

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

代码语言:javascript
复制
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'])

三,训练模型

代码语言:javascript
复制
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上可使用多进程读取数据
                         )

四,评估模型

代码语言:javascript
复制
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)

五,使用模型

六,保存模型

代码语言:javascript
复制
model.save('imdb_model.h5')
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-05-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 算法美食屋 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档