小鲁班资讯分类2.0 项目文档
00 min
2024-4-23

一、项目背景


  • 对于目前海量的金融资讯数据,公司内部传统的基于机器学习算法的文本分类平台(1.x版本)受限于特征提取的准确性和泛化能力,难以满足实际应用的需求,需要开发一种基于深度学习的高效准确的金融资讯分类处理系统(2.0版本),以提升公司内部的信息处理能力,来满足分析师和投资经理对数据的要求。

二、项目目标


  • 2.0版本分类平台相对1.x在文本分类,精确率需要提高至少5%,f1_score至少在90%;
  • 具有较好的响应速率,不影响用户使用。

三、项目构建


项目搭建过程中,先对数据进行分析、然后选用fastText模型作为Baseline,,随后使用Bert大模型进行训练,之后以Bert模型为Teacher,用TextCNN模型为Student做模型蒸馏,最后将蒸馏好的TextCNN模型部署上线。
  • 数据分析
  • fastText模型(Baseline)
  • Bert模型
  • TextCNN模型(知识蒸馏)

3.1 数据分析

  • 数据描述
    • 现有20000条数据源,以CSV格式文件表示,每条样本由新闻标题(文本)和新闻类别对应数字(标签)构成,每个类别数据各有40,000条数据
    • 新闻类别标签及对应数字表示:
  • 数据预处理:
    • 数据清洗:用正则去除乱码、去除英文字母等
    • 对于数据进行训练集、验证集、测试集划分,比例为8:1:1
    • 对样本进行分词以及标签按照对应格式转化(不同模型处理方式不一)
  • 数据分析
    • 样本分布:均衡分别,各标签类别为40,000条数据
    • 词长度分布:统计文本的长度的均值和标准差,样本长度基本在30左右
 

3.2 基线模型搭建

在本次版本迭代中,选择fastText模型作为Baseline,以快速看出深度学习模型的分类效果,同时供后面用Bert大模型做分类提供指标参考。

3.2.1 导入工具类

3.2.2 数据准备

使用fastText做文本分类任务,数据集中文本文件需要满足两种要求:
  • 文本文件中的每一行对应一个文档;
  • 文档的类别标签以 __label__name 为前缀放在文档的最前面;
对文本进行分词,既可以用jieba按照词性进行分词,也可用list内建函数,按照字符进行分词,实际按照模型效果好坏进行选择。
在源数据中,样本的标签为标签名对应的数值,这里读取class.text文件,获取标签值到标签名的索引.

3.2.3 模型搭建、训练及预测

结果:在10000条测试集上,训练得出的fastText模型的f1_score为88%。

3.2.4 模型优化

通过超参数搜索的方式对模型进行参数进行调优,从而尝试提升模型指标:
通过调优,模型提升0.5点,f1_score达到88.5%,调优效果较好。但是离项目指标<90%的指标还有待提升。

3.3 Bert模型训练

3.3.1 Config配置器

需要通过Config类保存数据处理、模型训练等各种参数,进行集中管理
  • 定义了模型名称、数据集路径、训练集、验证集、测试集文件路径、类别名单等信息。
  • 包含模型训练结果和量化模型存储结果的路径。
  • 配置了训练设备(GPU或CPU)、类别数、epoch数、mini-batch大小、句子长度等。
  • BERT预训练模型的路径、分词器、BERT模型配置、隐藏层大小等。

3.3.2 构建数据集函数

在Bert模型中,我们需要将样本基于字符进行分词,然后构建数据集工具build_dataset函数以及迭代器build_iterator函数
  • build_dataset() 自定义数据集
    • 根据配置信息构建用于模型训练的数据集;
    • 通过加载文本文件、分词、添加特殊标记(bert模型要求,包括[PAD]、[CLS]、 [UNK]),生成包含词汇索引、标签、序列长度和填充掩码的数据集;
    • 最终,函数返回训练集、验证集和测试集,以供模型使用。
  • build_iterator
    • DatasetIterater 类:
      • __init__:接收批次数据、批次大小、设备类型和模型名称,设置相关属性。
      • _to_tensor 函数:将批次数据转换为 PyTorch 的 Tensor 格式。
      • __next__ 函数:获取下一个批次的样本,处理不规则批次和索引溢出。
      • __iter__ 函数:返回迭代器对象本身。
      • __len__ 函数:获取迭代器的长度。
    • build_iterator 函数:
      • 根据配置信息和给定的数据集构建数据集迭代器对象。
      • 返回数据集迭代器

3.3.3 Bert模型搭建

构建Bert模型类,主要实现以下内容:
  • BertModel 类继承自 nn.Module,实现了一个基于BERT的文本分类模型。
  • 在初始化方法中,加载预训练的BERT模型和配置,并定义了一个全连接层用于文本分类。
  • 在前向传播方法中,通过BERT模型获取句子的表示,然后通过全连接层进行分类

3.3.4 Bert模型训练、评估和测试

训练函数train实现了模型的训练过程,使用了交叉熵损失函数和Adam优化器。具体包括以下内容:
  1. 优化器设置: 使用AdamW优化器,并设置了参数的权重衰减。
  1. 训练循环: 遍历每个epoch和每个batch,进行前向传播、计算损失、反向传播、参数更新。
  1. 评估: 每100个batch输出在训练集和验证集上的效果,包括训练损失、训练准确率、验证损失、验证准确率等。
  1. 保存模型: 若验证集上的损失更低,保存当前模型的参数。
  1. 时间计算: 计算训练的总时间。
模型验证函数 evaluate,用于在验证集或测试集上评估模型的性能。主要功能包括:
  1. 损失计算: 通过循环遍历数据集,计算模型在每个样本上的损失,并累加得到总损失。
  1. 预测结果记录: 记录模型对每个样本的预测结果和真实标签。
  1. 准确率计算: 根据记录的预测结果和真实标签计算模型的准确率。
  1. 测试集评估: 如果是测试集评估,额外计算分类报告和混淆矩阵。
测试函数test 用于在测试集上进行最终的模型测试。它调用了之前定义的 evaluate 函数,然后输出测试集上的损失、准确率、分类报告和混淆矩阵等信息。

3.3.4 构建模型训练主入口

结果:BERT模型在测试集上的表现是Test f1_score: 93% , 对比Baseline的fasttext模型最好的表现88.5%, 有了4.5%的提升, 效果显著性提升了,但是训练出的模型大小高达400M,模型较庞大,不符合项目上线要求,需要做蒸馏。

3.4 TextCNN

在工业级的应用中, 除了要求模型要有好的预测效果之外, 往往还希望它的"消耗"足够小. 也就是说一般希望部署在线上的应用模型消耗较小的资源. 这些资源包括存储空间, 包括算力。在该项目当中,我们以已经训练好的Bert模型为Teacher模型,以TextCNN模型为Student进行模型蒸馏。

3.4.1 配置Student的Config类

3.4.2 TextCNN模型构建(Student)

TextCNN(卷积神经网络用于文本分类)模型包含词嵌入层、多个卷积核大小的卷积层、池化层、随机失活层和全连接层。其中,卷积层通过不同大小的卷积核捕捉不同范围的文本信息,随机失活层用于防止过拟合,全连接层用于输出最终的分类结果。
notion image

3.4.3 模型损失构建

notion image
以下是模型蒸馏的基本训练步骤:
  1. 准备教师模型(bert大模型): 使用一个较大的模型进行训练, 这个模型在任务上表现很好。
  1. 使用教师模型生成软目标 对训练数据集进行推理,得到教师模型的输出概率分布(软目标)。这些概率分布包含了模型对每个类别的置信度信息。
  1. 准备学生模型(textcnn小模型): 初始化一个较小的模型,这是我们要训练的目标模型。
  1. 使用软目标和硬标签进行训练: 使用原始的硬标签(实际标签)和教师模型生成的软目标来训练学生模型。损失函数由两部分组成:
  1. 硬标签损失(通常为交叉熵损失): 学生模型的输出与实际标签之间的差距。(交叉熵损失
  1. 软目标损失: 学生模型的输出与教师模型生成的软目标之间的差距。这通常使用 KL 散度(Kullback-Leibler Divergence)来度量。
  1. 调整温度参数: KL 散度的计算涉及一个温度参数,该参数可以调整软目标的分布。温度较高会使分布更加平滑。在训练过程中,可以逐渐降低温度以提高蒸馏效果。
构建Teacher模型输出(软目标)
  1. 将教师模型设置为评估(推断)模式,通过 teacher_model.eval() 实现。在评估模式下,模型不会计算梯度,这有助于提高推断速度并减少内存消耗。
  1. 创建一个空列表 teacher_outputs,用于存储教师模型对训练集每个批次的输出。
  1. 遍历训练集迭代器 train_iter,对每个批次的数据调用教师模型,获取模型的输出。
  1. 将每个批次的输出添加到 teacher_outputs 列表中。
  1. 最后,返回包含教师模型对训练集所有批次输出的结果。
构建损失函数
notion image
通常采用的交叉熵损失函数, 有一点需要注意, F.cross_entropy()对输入有限制, 要求label必须是one-hot格式的. 但Teacher网络的输出soft targets是概率分布的形式, 不匹配,因此采用KL散度作为soft targets的loss, 注意: Pytorch中的KL散度函数可以接收概率分布形式的label.包含的步骤是:
  1. loss_fn 是用于一般的交叉熵损失函数,适用于训练 BERT 模型。
  1. criterion 是定义 KL 散度损失的 PyTorch 损失类。
  1. loss_fn_kd 是蒸馏损失函数,用于蒸馏训练。它接受三个参数:outputs(学生模型的输出),labels(真实标签),teacher_outputs(教师模型的输出)。
  1. 设置两个超参数:alpha 控制软损失和硬损失的权重,T 是温度参数,影响软化的程度。
  1. 计算学生模型(Student)的输出分布值和教师模型(Teacher)的输出分布值。对学生模型的输出进行 log_softmax 处理,对教师模型的输出进行 softmax 处理。
  1. 计算软损失,即学生模型和教师模型的输出分布之间的 KL 散度损失。
  1. 计算硬损失,即学生模型和真实标签的交叉熵损失。
  1. 计算总损失,通过加权软损失和硬损失得到。

3.4.4 知识蒸馏函数构建

使用知识蒸馏(Knowledge Distillation)的方式训练深度学习模型的训练函数完成的任务如下所示:
  1. 初始化优化器和其他训练参数,将CNN模型设置为训练模式,BERT模型设置为评估模式。
  1. 获取BERT模型的输出,作为教师模型的预测结果。
  1. 遍历每个epoch,对CNN模型进行训练。计算蒸馏损失(软损失)和交叉熵损失(硬损失)的组合,并进行反向传播和优化。
  1. 在训练过程中输出训练信息,包括训练损失、准确率以及在验证集上的表现。保存在验证集上表现最好的CNN模型。
  1. 在训练结束后,使用测试集对最终的CNN模型进行测试。
结论:
  • 模型大小只有24M,相比之下,模型大小明显减小
  • 模型准确率为91.55%,指标下降较小,在可接受范围内

4. 项目总结(问题罗列)

  • bert模型的整体架构
  • bert模型的两大预训练任务
  • 说一下transformer模型的基本架构
  • 什么是模型量化
  • 模型量化的实现方式
  • 模型蒸馏的损失函数
  • 介绍下LSTM模型
  • RNN和LSTM对比的优缺点
  • 简述下自我注意力机制原理
  • 在transformer中自注意力机制的计算方式
  • 什么是Word2Vec
  • bert和transformer模型的位置编码器有什么区别
  • python语言面向对象的特性
  • 什么是TextCNN模型
  • 怎么实现两个句子文本相似度的计算
  • 谈谈你对attention的理解
  • 什么是GBDT算法
  • 交叉熵损失的公式
  • 什么是逻辑回归算法
  • 二分类损失函数的表达式是什么
  • tranformer的掩码分为哪几种?
  • transfomer自注意力机制的时候处以根号下dk
  • fasttext的作用是什么
  • 缓解模型过拟合的方法有哪些
  • L1和L2正则化有什么区别?
  • 多文本多分类的任务的损失函数是什么?
  • 解释下什么是tf-idf