搜狗新闻文本分类竞赛

FlyAI搜狗新闻文本分类项目

1、项目简介

搜狗新闻文本分类项目是NLP的入门项目,本文主要介绍使用keras框架通过构建CNN+BiGRU网络实现在搜狗新闻文本数据集上91+的准确率。

2、数据集来源

该数据集来自若干新闻站点2012年6月—7月期间国内,国际,体育,社会,娱乐等18个频道的新闻数据。根据新闻正文内容分析新闻的类别数据集官网链接: The SogouTCE. 该数据集样例格式如下所示:

text,label
“福田欧曼·欧康杯”第六届全国卡车大赛厦门分站赛卡车宝贝进行才艺表演,汽车

FlyAI竞赛平台上 提供了超详细的参考代码,我们可以通过参加搜狗新闻文本分类预测练习赛进行进一步学习和优化。下面是准确率91+的代码实现其主要部分代码实现如下:

3、代码实现

3.1、算法流程及实现

算法流程主要分为以下四个部分进行介绍:

  1. 数据加载

  2. 构建网络

  3. 模型训练

数据加载

在FlyAI的项目中封装了Dataset类,可以实现对数据的一些基本操作,比如加载批量训练数据next_train_batch()和校验数据next_validation_batch()、获取全量数据get_all_data()、获取训练集数据量get_train_length() 和获取校验集数据量get_validation_length()等。具体使用方法如下:

# 引入Dataset类
from flyai.dataset import Dataset 
#创建Dataset类的实例
dataset = Dataset(epochs=10, batch=128) 
​
# dataset.get_step()返回训练总步长
# 加载processor.py中处理好的数据,一次性加载所有的train和val数据
x_train, y_train, x_val, y_val = dataset.get_all_processor_data()
print('Load data done!')

对每条新闻数据的读取和处理是在processor.py文件中完成。具体实现如下:

from flyai.processor.base import Base
import re
import jieba
import numpy as np
from create_dict import load_dict, load_label_dict
​
MAX_LEN = 128  # 最大词数,分析数据集后给出的合理值
​
​
class Processor(Base):
    def __init__(self):
        super(Processor, self).__init__()
        # 加载字典文件
        self.w2idx, self.idx2w = load_dict()
        self.l2idx, self.idx2l = load_label_dict()
​
    # 该参数[text]需要与app.yaml的Model的input-->columns->name 一一对应
    def input_x(self, text):
        '''
        参数为csv中作为输入x的一条数据,该方法会被Dataset多次调用
        '''
        # 对数据进行清洗
        text_line = re.sub(r',{1,}', ',', re.sub(u"([^\u4e00-\u9fa5\u0030-\u0039\u0041-\u005a\u0061-\u007a“”.?!(()){}【\[\]】:~,。…\"])",",", text))
        # print('text_line', text_line)
        terms = jieba.cut(text_line, cut_all=False)
​
        truncate_terms = []
        for term in terms:
            truncate_terms.append(term)
            # 如果text词数超过MAX_LEN提前跳出循环
            if len(truncate_terms) >= MAX_LEN:
                break
​
        index_list = [self.w2idx[term] if term in self.w2idx
                      else self.w2idx['_UNK_'] for term in truncate_terms]
​
        if len(index_list) < MAX_LEN:
            index_list = index_list+[self.w2idx['_PAD_']]*(MAX_LEN-len(index_list))
        return index_list
​
    # 该参数[label]需要与app.yaml的Model的output-->columns->name 一一对应
    def input_y(self, label):
        '''
        参数为csv中作为输入y的一条数据,该方法会被Dataset多次调用
        '''
        y = np.zeros(len(self.l2idx))
        if label in self.l2idx:
            label_index = self.l2idx[label]
            y[label_index] = 1
        return y
​
    def output_y(self, data):
        '''
        验证时使用,把模型输出的y转为对应的结果
        '''
        out_y = np.argmax(data)
        if out_y in self.idx2l:
            out_y = self.idx2l[out_y]
        else:
            out_y = '未知标签'
        return out_y

构建网络

由于是搜狗新闻文本类数据,这里我们可以使用一维卷积Conv1D + BiGRU来构建网络,网络结构如下所示:

# ----------------------------构建网络---------------------------- #
# 数据输入格式
input_x = Input(shape=(MAX_LEN,), dtype='int32', name='input_x')
​
# embedding层
embedden_seq = Embedding(input_dim=word_vocab, output_dim=embed_dim, input_length=MAX_LEN, name='embed')(input_x)
​
# 第一个卷积层,由于要处理文本数据,这里我们使用一维卷积Conv1D,conv_dim个卷积核,大小5x1,卷积模式SAME,
# 激活函数relu, 最终输出张量的shape和输入的一致
conv1 = Conv1D(filters=conv_dim, kernel_size=5,  padding='same', activation='relu')(embedden_seq)
# 随机断开二分之一的网络连接,防止过拟合
drop1 = SpatialDropout1D(0.5)(conv1)
# 压扁不影响batch_size大小
fl1 = Flatten()(drop1)
​
​
# 批标准化,对数据进行标准化处理
bn1 = BatchNormalization()(embedden_seq)
# 双向GRU网络,对数据进行前向后向化处理,更好的获取上下文信息
bGRU1 = Bidirectional(GRU(rnn_size, activation='selu', return_sequences=True, implementation=1), merge_mode='concat')(bn1)
# 随机断开四分之一的网络连接,防止过拟合
drop2 = SpatialDropout1D(0.5)(bGRU1)
# 压扁不影响batch_size大小
fl2 = Flatten()(drop2)
​
# 将CNN网络和GRU网络输出连接起来
cont1 = concatenate([fl1, fl2])
​
# 添加隐藏层神经元的数量和激活函数
dense1 = Dense(256, activation='relu')(cont1)
# 最终经激活函数softmax输出对应位置的predict概率
predict = Dense(class_num, activation='softmax')(dense1)
​
# 传入数据
k_model = keras.Model(input_x, predict)
​
# 打印网络详情
k_model.summary()
​
# 执行模型编译,传入优化器名称并修改相应参数
k_model.compile(optimizer=keras.optimizers.adam(lr=0.001, decay=1e-6),
                loss='categorical_crossentropy', metrics=['accuracy', ])

运行summary()方法后输出的网络结构如下图:

模型训练

这里我们设置了epoch为5,batch为128,采用adam优化器来训练网络,EarlyStopping可以加速调参过程。然后通过调用FlyAI提供的train_log方法可以在训练过程中实时的看到训练集和验证集的准确率及损失变化曲线。

# 1. 定义early_stopping规则
early_stopping = EarlyStopping(monitor='val_acc', patience=2)
​
# 2. 将数据fit到网络,训练模型,以BATCH个样本为一个batch进行迭代,EPOCHS为要迭代的轮次数
k_model.fit(x_train, y_train,
            batch_size=args.BATCH,
            validation_data=(x_val, y_val),
            epochs=args.EPOCHS,
            verbose=1,
            callbacks=[early_stopping])

3.2、最终结果

通过使用自定义CNN网络结构+双向GRU网络的方法,在epoch为10,batch为128的条件下使用adam优化器下不断优化模型参数,使用early_stopping规则在model训练达到early_stopping条件时提前终止训练提高model优化效率,最终模型在测试集的准确率达到91+。 该项目的可运行代码如下:完整代码链接

参考链接:

发布了35 篇原创文章 · 获赞 22 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/iFlyAI/article/details/103030183