【木棉花】基于Pytorch的文本分类AI模型 原创
摘要
作为一种革命性的神经网络架构,Transformer改变了处理变长序列的方式,其独有的自注意力机制使其能够高效完成智能对话,文本分类,机器翻译等自然语言处理任务。本篇文章所讨论的研究内容是基于自定义的Transformer神经网络实例完成一个文本分类任务——英文文本的文风分类任务,旨在解决传统文风分类任务方法在多语义和复杂语境理解的局限性。
研究过程涵盖如下部分:首先介绍对给定数据集的预处理的流程;接着,我们将阐述如何针对英文文本的文风分类任务设计一个Transformer神经网络实例;最后,我们将展示AI模型的训练过程,对完成训练的模型的相关性能进行评估,并对模型进行相关优化。整个实验过程基于pytorch的python编程环境。
引言
Transformer模型是一种用于处理序列数据的强大神经网络架构,特别是在自然语言处理(NLP)领域取得了显著的效果。Transformer的基本组成部分包括如下几个关键层:
- 输入层(Input Layer):
- 词嵌入(Word Embeddings): 将词汇转换为稠密的向量表示。
- 位置编码(Positional Encoding): 添加位置信息,因为Transformer没有内在的顺序概念,位置编码确保模型能够理解词序。
- Encoder(编码器):
- Multi-Head Attention: 允许模型在多个表示子空间中并行执行自我注意力机制。
- Position-wise Feed-Forward Networks (FFNs): 提供非线性变换,通常包括两个全连接层,中间可能有激活函数。
- Layer Normalization: 在每一层的残差连接前后应用,帮助加速收敛和避免梯度消失问题。
- Dropout: 用于正则化,减少过拟合。
- Decoder(解码器):
- Masked Multi-Head Attention: 类似于编码器中的Multi-Head Attention,但是加入了mask以防止当前位置访问未来位置的信息。
- Multi-Head Attention with Encoder Outputs: 这允许解码器关注编码器的输出,这是序列到序列任务的关键部分。
- Position-wise Feed-Forward Networks (FFNs): 提供非线性变换,通常包括两个全连接层,中间可能有激活函数。
- Layer Normalization: 在每一层的残差连接前后应用,帮助加速收敛和避免梯度消失问题。
- Dropout: 用于正则化,减少过拟合。
- Output Layer(输出层):
- Linear Layer(线性层): 将解码器的输出映射到目标词汇表的大小。
- Softmax Layer: 应用softmax函数,将线性层的输出转换为概率分布,表示每个词汇被选中的概率。
下图是Transformer模型的架构图:
对不同的英文文本进行文风分类这一应用具有多领域和多方面的价值。文风分类不仅有助于识别和理解不同文化背景下的语言使用习惯,促进跨文化的理解和交流,而且在AI文本生成领域,文风分类技术可以用于控制模型生成文本的风格,使得生成的文本更加贴近特定的受众或情境,如新闻报道、小说创作或广告文案。因为在传统方法的基础上实现的文风识别功能效果欠佳,而Transformer神经网络在处理文本这类变长序列时具有非常好的效果,所以我们可以利用Transformer神经网络训练一个合格的模型,用于完成文本分类任务。
方法
1.数据预处理
本次研究所用到的数据集en_test来自ModelScope社区的数据集仓库,数据集的格式是csv文件,此数据集下载网址如下:
http://www.modelscope.cn/datasets/iic/nlp_style_classification_enlish_testset
此数据集总共约有7400条英文文本样本,而样本的标签分为如下四个类型:
文风标签 | 含义 |
news | 新闻文风,即各类常用书面语 |
tech | 科技文风,包括技术文档,科技文献等 |
spoken | 口语文风,各类非书面的口语表达 |
ecomm | 电商文风,电商场景的标题,评论,描述等 |
在实验环境中导入en_test.csv后,我们首先对此数据集中的所有文本样本进行数据清洗:将句子文本中的所有英文字符归一化为小写英文字符,同时去除标点符号和数字。数据清洗完成之后,得到的新数据将被放置于‘cleaned_text’的条目下。
data['cleaned_text'] = data['text'].apply(clean_text)
接着,提取数据中的英文单词,并构建一个词汇表。此词汇表的数据结构是一个字典,字典中包含100000条键值对(对应100000个不同的单词),其中键对应的是英文单词的字符串,值对应的是该英文单词被分配的索引(从0到100000的整数序号)。实际单词的数量约为120000,本研究只选取前100000个相对高频的词汇。另外,我们还需要在词汇表中添加两个重要的词汇:<UNK>,表示未知词汇,用于统一表示词汇表中未收录的低频词汇;<PAD>,表示填充词汇,用于填充某个文本序列中空缺的位置以保证所有文本序列长度一致。
完成了前面的准备工作后,我们就可以把数据集中的文本映射成唯一的数字序列,得到的新序列数据将被放置于‘indices’的条目下。转换得到的序列的数据格式是列表,列表的每一项表示一个词汇在词汇表中对应的序号。
data['indices'] = data['cleaned_text'].apply(text_to_indices)
到目前为止,数字序列的长度并不是统一的。经统计,数据集的单个文本样本的词汇规模最多达到了128,而平均词汇规模是16,由此可知文本的数字序列的前部分所占权重是比较大的,因此我们将所有数字序列统一填充(即填充<PAD>在词汇表中对应的序号)或裁剪成包含48个元素的列表,即统一的序列长度是48。得到的新数据将被放置于
‘padded_indices’的条目下。
data['padded_indices'] =data['indices'].apply(pad_sequence)
统一文本的数字序列长度后,我们将四类文风标签编码成4个one-hot向量,并将最新的数据集划分为训练集和测试集。这样之后,文本数据就从数字序列群转换成保存在数据加载器(DataLoader)里的张量。后续训练过程中,我们根据批次大小将二维张量(行数是批次大小,列数是文本的数字序列的维度)加入到神经网络中训练。
train_loader = DataLoader(train_dataset, batch_size=BATCH_SIZE, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=BATCH_SIZE, shuffle=False)
2.Transformer神经网络的定义
为了高效地应对文本分类任务,我们定义如下Transformer神经网络架构:
第一层:词嵌入层。输入的张量会进行词嵌入操作,即原本文本的数字序列中的每一个序号项都会转换成一个稠密的多维向量,输入张量的维度也由二维增加成了三维。这么做的结果是,先前的词汇表中每个词汇将不再映射到某个整数索引上,取而代之映射到某个多维向量上,并且有助于捕捉语义和体现语法关系。
embedding = nn.Embedding(vocab_size, d_model)
第二层:位置编码层。这一层可以为文本数据(张量形式)添加位置信息,因为Transformer没有内在的顺序概念,而位置编码可以确保模型能够理解词序。此外,此层还携带了dropout子层用于正则化以减小模型的过拟合现象。
self.positional_encoding = PositionalEncoding(d_model, max_len=max_sequence_length)
第三层:Transformer编码层。这一层包含了四个Transformer编码子层,每一层都有一个多头自注意力模块和一个前馈神经网络模块,能够处理批量输入,并且按照
batch_first
的顺序接收数据。
self.transformer = nn.TransformerEncoder(
nn.TransformerEncoderLayer(d_model=d_model, nhead=nhead, batch_first=True,dim_feedforward=dim_feedforward),
num_layers=4)
第四层:线性分类层。这一层将得到一个batch_size(批次)×4(文风类别数目)规模的张量,它携带了本次输入样本批次的类别概率分布信息,作为神经网络最终的输出。
self.classifier = nn.Linear(d_model, num_classes)
以下是此神经网络整体的架构演示图
3.训练过程
完成了Transformer神经网络的构建后,我们实例化一个模型并进行模型训练,梯度下降法采用小批量梯度下降。其中,学习率初始设置为0.0001,损失函数使用交叉熵损失函数,计算方式如下(对于单个样本)
优化器则选择Adam,其动态调整学习率的功能能够为模型训练提供很大的帮助。模型训练的过程中,我们总共设置了100个周期,每个周期内模型都会通过优化器进行批量的梯度下降,利用反向传播算法不断更新神经网络中的参数矩阵。此外,在训练过程的间隙,我们植入一些代码用于测试模型实时的准确率。
实验
性能分析
训练完成后,我们得到三个曲线图。如下曲线图代表交叉熵损失函数的值随训练数据输入和周期迭代的变化曲线。可见,随着训练数据的加入,损失函数的值以震荡的方式逐渐减小并趋于0,梯度也随之收敛。
如下两图代表模型对文本样本的文风分类预测准确率,其中第一个图的分类预测采用top1,即只采用预测向量中概率值最大的分类作为预测值;第二个图的分类预测采用top2,即采用预测向量中概率值最大和次大的分类作为两个预测值,这意味着当文本的实际分类与两个预测分类中的任意一个相同时,其便被认定为预测成功。
显然,这个文本分类模型的top1分类预测准确率始终小于75%,top2分类预测准确率始终小于89%。如下是模型最终的top1分类预测准确率和top2分类预测准确率,分别约为68%和82%,可见目前模型性能是比较低的。
优化
经分析得出,模型的准确率偏低且出现瓶颈的原因在于:词嵌入层性能过低。由于先前创建的Transformer神经网络中只定义了一个简单基本的词嵌入层,其功能仅仅是将词汇表中的每个单词映射到一个固定大小的向量空间中,由于缺乏训练,这个词嵌入层缺乏上下文信息,泛化能力差,所以其性能表现较低。
因此,改进后的文风分类模型将采用预训练的词嵌入层。预训练模型通常在大规模的无标注文本数据上进行训练,学习到词与词之间的复杂关系,从而生成高质量的词向量。BERT将作为优化本模型所采用的预训练模型,且我们选择的版本是轻量级的bert-base-uncased。
由于使用预训练的模型作为词嵌入,数据预处理的代码需要重写,我们将不必为文本数据建立词汇表,而是直接把文本样本交给导入的分词器进行tokenize。优化后,模型的性能如下,准确率(top1)约为86%,相比原来的模型,准确率提升了约18个百分点。
下图是每种类别在被预测时的独立准确率,可见,如果文本样本属于电商文风,那么它将很容易被模型检测处来,如果文本样本属于口语文风,则其容易被错误分类。
总结
经过本次研究,我们成功利用Transformer神经网络架构训练出了应对文本文风分类的AI模型。第一个版本的文本分类模型因为词嵌入功能过于简单的原因而性能欠佳,准确率仅有68%,因此我们替换了神经网络架构的词嵌入,改用BERT预处理数据,这样之后第二个版本的文本分类模型的准确率(top1)达到了86%,相比之下提升了约18个百分点。
参考文献
[1] 神经网络与深度学习/邱锡鹏著. —北京:机械革命出版社,2020.3