简介
Transformer 的核心思想是利用自注意力机制(self-attention) - 能注意到输入序列的不同位置以计算该序列的表示的能力。基于多头注意力机制,每个单词会被转化为 Token (词元)。
核心机制
位置编码
Transformer 中不包含任何的循环或卷积,因此添加了位置编码,为模型提供一些关于单词在句子中相对位置的信息。
位置编码向量被加到嵌入(embedding)向量中。嵌入表示一个 d 维空间的标记,在 d 维空间中有着相似含义的标记会离彼此更近。但嵌入并没有对在一句话中的词的相对位置进行编码,因此当加上位置编码后,单词将基于他们含义的相似度以及他们在句子中的位置,在 d 维空间中离彼此更近。
点积注意力
Transformer 使用的注意力函数共有三个输入:Q 请求、K 主键、V 数值。
点积注意力被缩小深度的平方根倍,这样做是因为对于较大的深度值,点积的大小会成倍增大,从而推动 softmax 函数往仅有很小的梯度的方向靠拢,导致 hard 的 softmax。
多头注意力
多头注意力由四部分组成:
- 线性层并拆分为多头。
- 按比例缩放点积注意力。
- 多头及联。
- 最后一层线性层。
每个多头注意力块有三个输入:Q 请求、K 主键、V 数值。这些输入经过线行(Dense)层,并会被拆分为多头。
Q、K、V被拆分为多头,而不是单头,因为多头允许模型共同注意来自不同表示空间的不同位置的信息。在拆分后每个头部的维度减少,因此总的计算成本与有全部维度的单个注意力头相同。
掩码
掩码一批序列中所有的填充标记,其确保模型不会将填充物作为输入。该 mask 表示填充值 0 出现的位置:这些位置输出 1,否则输出 0。
点式前馈网络
点式前馈网络由两个全连接层组成,两层之间插入一个 ReLU 激活函数。
编码器
编码器包含以下部分:
输入嵌入(
Input Embedding)。位置编码(
Positional Encoding)。N个编码器层(encoder layers),每个编码器层包含以下子层:- 多头注意力(有填充掩码)。
- 点式前馈网络。
每个子层在其周围有一个残差连接,然后进行层归一化。归一化是在
d_model最后一个维度完成的。残差连接是为了避免深度网络中的梯度消失问题。
每个子层的输出是LayerNorm(x + Sublayer(x))。
输入通过嵌入(embedding)后,该嵌入与位置编码相加。该加法结果的输出会作为编码器层的输入。编码器的输出即解码器的输入。
解码器
解码器包含以下部分:
输出嵌入(
Output Embedding)。位置编码(
Positionak Encoding)。N个编码器层(decoder layers),每个解码器层包含以下子层:- 掩码的多头注意力。
- 多头注意力(用填充掩码),
V数值和K主键接收编码器输出作为输入,Q接收掩码的多头注意力子层的输出。 - 点式前馈网络。
每个子层在其周围有一个残差连接,然后进行层归一化。每个子层的输出是
LayerNorm(x + Sublayer(x))。归一化是在d_model最后一个维度完成的。
当Q接收到解码器的第一个注意力块的输出,并且K接收到编码器的输出时,注意力权重表示根据编码器的输出赋予解码器输入的重要性。换句话说,解码器通过查看编码器的输出和对其自身输出的自注意力,来预测下一个词。
目标经过一个嵌入后,该嵌入与位置编码相加,该加法结果就是解码器层的输入。解码器的输出是最后线性层的输入。
本文是基于《用Transformers处理自然语言》一书的简要学习记录,并没有很详细的方案,有兴趣的话可以阅读原文。
文本分类
文本分类是NLP中最常见的任务之一。另一种常见的文本分类是情感分析,其目的是识别特定文本的倾向性。
数据集标记化
1 | print(tokenize(emotions["train"][:2])) |
训练文本分类器
Tranformer 提取特征
1 | # 使用预训练分类器 |
特征矩阵
1 | def extract_hidden_states(batch): |
可视化训练集 使用强大的 UMAP 算法将向量向下投射到二维。
1 | from umap import UMAP |
微调 Transformer
1 | # 加载预训练模型 |
文本摘要
某一时刻可能需要对一份报告、研究文章、财务报告进行摘要,摘要是一个经典的序列到序列(seq2seq)任务,有一个输入文本和一个目标文本。这也是 Transformer 编码器-解码器的优势所在。
CNN/DailyMail 数据集大约有 30w 条新闻文章及对应的摘录组成,这些摘要由 CNN 和 DailyMail 在其文章中附加的要点组成。
1 | # 数据概况 |
文本摘要流水线:
GPT-2T5BARTPEGASUS
摘要评比:
BLEU -> SacreBLEUROUGE
问答系统
在某个时刻你可能需要在海量数据中寻找所需要的信息,搜索引擎会首先检索文件,然欧进行一个额外的处理步骤,提取带有相应段落和网页的答案片段。
这种技术背后的方法被称为问题回答 QA。最常见的是提取式 QA,问题的答案被识别为文档中的一段文字,首先检索文档,然后从中提取答案。
基于评论的问答系统
SubjQA 由超过 1w 条英文的顾客评论组成。
1 | from datasets import get_dataset_config_names |
文本中提取答案
从文本中提取答案的最常见的方法是把问题看作一个跨度分类任务,其中答案跨度的开始和结束符号作为模型需要预测的标签。
1 | from transformers import AutoTokenizer |
文本已经被标记化,现在需要用一个 QA 头来实例化这个模型,并通过前向传递来运行输入:
1 | import torch |
为了得到最终的答案,可以计算开始和结束标记对数的 argmax,然后从输入中切出跨度。
1 | import torch |
很好,它成功了!
处理长段落文本
在 tokenizer 中设置 return_overflowing_tokens=True 参数启用滑动窗口(Transformer 训练预提取后的短信特征)。
检索器类型
TF-IDFBM25EmbeddingDPR
评估检索器
- 使用检索器内置的
eval()方法。 - 构建一个自定义流水线,将检索器与
EvalRetriever类结合起来。
评估阅读器
- 完全匹配(
EM) F1-score
性能优化
探讨四种互补的技术:知识蒸馏、量化、剪枝、开放网络神经交换(ONNX)格式及 ONNXRuntime(ORT)进行图的优化。
知识蒸馏
知识蒸馏是一种通用的方法,用于训练一个较小的学生模型来模仿一个较慢的、较大的、但表现较好的教师模型的行为。
Optuna 超参数优化框架。
量化
量化采取了一种不同的方法;它不是减少计算的数量,而是通过用 8 位整数(INT8)而不是通常的 32 位浮点(FP32)这样的低精度数据类型来表示权重和激活,从而使它们更有效率。
减少比特数意味着所产生的模型需要更少的内存存储,而且像矩阵乘法这样的操作可以通过整数运算更快地进行。
量化的基本思想是,我们可以将每个张量中的浮点值 f “离散化”,将其范围[fmax, fmin]映射到一个更小的[qmax]的定点数字 q 中。定点数字 q 的范围[qmax, qmin],并对两者之间的所有数值进行线性分配。
对于深度神经网络,通常主要有以下三种量化方法:
- 动态量化。当使用动态量化时,在训练过程中没有任何变化,只有在推理过程中才会进行调整。这种方法是动态的,量化是即时进行的,其意味着所有的矩阵乘法都可以用高度优化的
INT8函数来计算。 - 静态量化。静态量化是通过在推理时间之前观察数据的代表性样本的激活模式来实现的。
- 量化训练。量化训练中不使用
INT8值,而是对FP32值进行四舍五入,以模拟量化的效果。
剪枝
权重修剪模型使得更加稀疏 top-K。
ONNX
ONNX 是一个开放的标准,它定义了一套通用的运算符和通用的文件格式,以表示各种框架的深度学习模型,包括 PyTorch 和 TensorFlow。当一个模型被导出到 ONNX 格式时,这些运算符被用来构建一个计算图(通常称为中间表示法),表示数据在神经网络中的流动。
从头开始训练一个 Transformer
在这部分将决定哪种架构最适合这项任务,初始化一个没有预训练权重的新模型,设置一个自定义数据加载类,并创建一个可扩展的训练循环。
创建Transformer
加载 gpt2-xl 的配置,使用相同的超参数,只为新的标记器调整词汇量大小。
1 | from transformers import AutoConfig, AutoModelForCausalLM, AutoTokenizer |
配置超参数
设置训练用的超参数,将其封装在一个命名空间中,便于访问。
1 | from argparse import Namespace |
优化器
1 | no_decay = ["bias", "LayerNorm.weight", "ln_1.weight", "ln_2.weight", "ln_f.weight"] |
损失函数与指标
1 | def evaluate(model, eval_dataloader, max_eval_steps=-1): |
训练与检查点
1 | model.train() |
有兴趣的话可以去研究下 minimind ,是一篇很好的入门学习教程。
总结
当你在实践中遇到问题时,不妨静下心来去看看底层原理,也许问题就自而然就解决方案了。
个人备注
此博客内容均为作者学习《Transformers》所做笔记,侵删!
若转作其他用途,请注明来源!