1. 什么是transformer?
Transformer 的核心思想是:通过注意力机制,让模型自己学会关注输入序列中哪些部分是重要的。
Transformer 模型由以下几个关键部分组成:
(1)输入表示(Input Representation)
输入是一个序列(比如一句话),每个词会被转换成一个向量(称为词嵌入,Word Embedding)。
例如,句子 “I love cats” 会被转换成三个向量:
[I的向量, love的向量, cats的向量]。
(2)位置编码(Positional Encoding)
Transformer 没有显式的顺序信息(不像 RNN 那样按顺序处理),所以需要通过位置编码来告诉模型每个词的位置。
位置编码是一个与词嵌入维度相同的向量,直接加到词嵌入上。
例如,
"I" 的位置编码会加到 **I的向量** 上, "love" 的位置编码会加到 **love的向量** 上。
(3)自注意力机制(Self-Attention)
自注意力机制的作用是:让模型学会关注输入序列中哪些词是相关的。
举个例子:
对于句子 “The cat sat on the mat”,模型需要知道:
“cat” 和 “sat” 是相关的。
“sat” 和 “on” 是相关的。
“on” 和 “the mat” 是相关的。
自注意力机制会计算每个词与其他词的关系,并生成一个新的表示。
(4)多头注意力(Multi-Head Attention)
为了让模型捕捉到更丰富的关系,Transformer 使用了多头注意力。
简单来说,就是让模型从多个不同的角度(子空间)来学习词与词之间的关系。
例如,一个注意力头可能关注语法关系,另一个注意力头可能关注语义关系。
(5)前馈神经网络(Feed-Forward Network, FFN)
在自注意力机制之后,Transformer 会使用一个前馈神经网络对每个词的表示进行进一步处理。
这个网络通常是两层的全连接网络,中间使用激活函数(如 ReLU)。
(6)残差连接和层归一化(Residual Connection & Layer Normalization)
为了帮助模型更好地训练,Transformer 在每个子层(如自注意力、前馈网络)之后都会添加残差连接和层归一化。
残差连接:将输入直接加到输出上,避免梯度消失。
层归一化:对每个样本的特征进行归一化,加速训练。
(7)编码器和解码器(Encoder & Decoder)
Transformer 分为两部分:
编码器:将输入序列(如英文句子)转换成一组特征表示。
解码器:根据编码器的输出,生成目标序列(如中文句子)。
编码器和解码器都由多个相同的层堆叠而成。
2. Transformer中的token怎么理解?
token 通常被翻译为 “词元” 或 “标记”。
在Transformer模型中,token 是输入文本的基本处理单元,可以是单词、子词或字符,具体取决于分词方式。
1. 单词级别的Token
将每个单词作为一个独立的token。
例子:
句子:"I love natural language processing."
Token:["I", "love", "natural", "language", "processing", "."]
2. 子词级别的Token
使用子词分词方法(如Byte Pair Encoding, BPE)将单词拆分为更小的单元。
例子:
句子:"unhappiness"
Token:["un", "happi", "ness"]
3. 字符级别的Token
将每个字符作为一个token。
例子:
句子:"cat"
Token:["c", "a", "t"]
4. 特殊Token
Transformer模型还使用一些特殊token,如:
[CLS]:分类任务的起始标记。
[SEP]:分隔句子。
[PAD]:填充序列至相同长度。
[UNK]:未知词。
例子:
句子:“How are you?”
Token:[“[CLS]”, “How”, “are”, “you”, “?”, “[SEP]”]
3. Transformer的工作流程
例子,说明 Transformer 如何将英文句子翻译成中文:
输入句子:"I love cats"
1. 输入表示:
将每个词转换成向量:
[I的向量, love的向量, cats的向量]。
2. 位置编码:
为每个词添加位置信息:
[I的向量 + 位置1, love的向量 + 位置2, cats的向量 + 位置3]
3. 编码器:
通过自注意力机制和前馈网络,生成每个词的上下文表示。
4. 解码器:
根据编码器的输出,逐步生成目标句子 “我喜欢猫”。
解码器会关注编码器的输出以及已经生成的部分目标句子。
4. Transformer和注意力机制的关系?
注意力机制是一种计算权重的方法,用于决定模型在处理输入时应该“关注”哪些部分。它的核心思想是:
- 动态权重分配:根据输入的不同部分的重要性,动态分配权重。
- 上下文感知:能够捕捉输入序列中各个元素之间的关系。
注意力机制的例子:
假设我们要将英文句子 “I love cats” 翻译成中文 “我喜欢猫”。在翻译过程中:
- 模型需要知道 “I” 对应 “我”,“love” 对应 “喜欢”,“cats” 对应 “猫”。
- 注意力机制会计算每个词与其他词的关系,并生成一个新的表示。
虽然注意力机制本身非常强大,但它通常需要与其他模型(如 RNN 或 CNN)结合使用。Transformer 的提出是为了解决以下问题:
(1)RNN 的局限性
顺序计算:RNN 需要按顺序处理序列数据,无法并行计算,导致训练速度慢。
长距离依赖问题:RNN 难以捕捉序列中远距离元素之间的关系。
(2)注意力机制的局限性
单独使用注意力机制:注意力机制通常需要与 RNN 或 CNN 结合使用,无法独立构建完整的模型。
计算复杂度:注意力机制的计算复杂度较高,直接应用于长序列时效率低下。
(3)Transformer 的优势
完全基于注意力机制:Transformer 完全摒弃了 RNN 和 CNN,仅依赖注意力机制来处理序列数据。
并行计算:Transformer 可以同时处理整个序列,训练速度更快。
长距离依赖:自注意力机制能够直接捕捉序列中任意两个元素之间的关系。
(1)注意力机制的优缺点
优点:
动态权重分配:能够根据输入动态调整权重。
上下文感知:能够捕捉序列中各个元素之间的关系。
缺点:
计算复杂度高:注
无法独立构建模型:通常需要与 RNN 或 CNN 结合使用。
(2)Transformer 的优缺点
优点:
并行计算:可以同时处理整个序列,训练速度更快。
长距离依赖:自注意力机制能够直接捕捉序列中任意两个元素之间的关系。
通用性:不仅适用于 NLP,还可以用于 CV、语音等领域。
缺点:
计算复杂度高:虽然 Transformer 可以并行计算,但注意力机制的计算复杂度仍然较高。
内存占用大:由于需要存储注意力权重,Transformer 的内存占用较大。
5. Transformer插入位置的讨论?
(1)效率优化
稀疏注意力(Sparse Attention)
:
例如 Longformer、BigBird,通过减少注意力计算的范围,降低计算复杂度。
线性注意力(Linear Attention
):
例如 Performer,将注意力计算从二次复杂度降低到线性复杂度。
低秩分解(Low-Rank Factorization)
:
例如 Linformer,通过低秩近似减少计算量。
(2)长序列处理
长距离依赖
:
例如 Reformer,使用局部敏感哈希(LSH)来减少长序列的计算开销。
分块处理(Chunking
):
例如 Longformer,将长序列分成多个块,分别计算注意力。
(3)多模态融合
视觉 Transformer(Vision Transformer, ViT
):
将 Transformer 应用于图像分类任务,将图像分成多个 patch,然后像处理序列一样处理这些 patch。
多模态 Transformer
:
例如 CLIP,将文本和图像输入到同一个 Transformer 中,进行多模态学习。
(4)预训练与微调
预训练模型
:
例如 BERT、GPT、T5,通过大规模预训练学习通用特征,然后在特定任务上微调。
自监督学习
:
例如 SimCLR、MAE,通过设计自监督任务(如掩码预测)来预训练 Transformer。
(5)结构改进
层级 Transformer
:
例如 Swin Transformer,通过分层设计减少计算量。
动态注意力(Dynamic Attention
):
例如 Dynamic Transformer,根据输入动态调整注意力机制。
作为特征提取器:Transformer 编码器可以用于提取输入序列的上下文特征。
作为生成模型:Transformer 解码器可以用于生成目标序列(如文本、图像)。
作为多模态融合模块:Transformer 可以同时处理多种模态的数据(如文本 + 图像)。
作为预训练模型:Transformer 可以通过大规模预训练学习通用特征,然后在特定任务上微调。
6. Transformer 模型的输入
Transformer 模型的输入通常是 二维或三维 的数据,具体取决于任务类型和数据处理方式。以下是详细解释和示例:
1. 二维输入(Sequence Data)
形状:(batch_size, sequence_length)
适用场景:文本分类、机器翻译等任务。
输入是已经分词并映射为整数索引的序列。
示例:
假设有一个批次大小为 2 的输入,每个序列长度为 5:
input_ids = torch.tensor([[101, 2056, 3010, 102, 0],
[101, 3331, 102, 0, 0]])
形状为 (2, 5),其中:
2 是批次大小(batch size)。
5 是序列长度(sequence length)。
每个整数表示一个 token 的索引。
2. 三维输入(Sequence Data with Embeddings)
形状:(batch_size, sequence_length, embedding_dim)
适用场景:输入是已经通过嵌入层(Embedding Layer)映射为稠密向量的序列。
适用于大多数 Transformer 模型(如 BERT、GPT)。
示例:
假设嵌入维度为 768,批次大小为 2,序列长度为 5:
embeddings = torch.randn(2, 5, 768)
形状为 (2, 5, 768),其中:
2 是批次大小(batch size)。
5 是序列长度(sequence length)。
768 是嵌入维度(embedding dimension)。
3. 特殊情况:多维输入(如图像、视频)
形状:(batch_size, sequence_length, embedding_dim) 或 (batch_size, height, width, channels)
适用场景:图像、视频等非序列数据需要先转换为序列形式。
例如,Vision Transformer(ViT)将图像分割为 patch,然后将每个 patch 展平为向量。
示例:
假设输入是一张 224x224 的 RGB 图像,patch 大小为 16x16:
- 图像被分割为 (224/16) * (224/16) = 196 个 patch。
- 每个 patch 展平为 16 * 16 * 3 = 768 维的向量。
- 输入形状为 (batch_size, 196, 768)。
4. 输入的处理流程
Transformer 的输入通常经过以下步骤:
Tokenization:
将原始文本分割为 token(如单词、子词)。
示例:“I love NLP” → [“I”, “love”, “NLP”]。
Index Mapping:
将 token 映射为整数索引。
示例:[“I”, “love”, “NLP”] → [101, 2056, 3010]。
Embedding:
将索引映射为稠密向量。
示例:[101, 2056, 3010] → (3, 768) 的嵌入矩阵。
Positional Encoding:
添加位置编码以保留序列顺序信息。
输入 Transformer:
将嵌入后的数据输入 Transformer 模型。
- 具体例子
文本分类任务
输入文本:[“I love NLP.”, “Transformers are powerful.”]
Tokenization:
tokens = [["I", "love", "NLP", "."],
["Transformers", "are", "powerful", "."]]
Index Mapping:
input_ids = [[101, 2056, 3010, 102],
[101, 3331, 102, 0]]
Embedding:
embeddings = torch.randn(2, 4, 768)
输入 Transformer:
形状为 (2, 4, 768)。