Skip to main content

Transformer架构知识

更多可参考本科毕业论文(后续补充)

Transformer三类架构

​ Transformer架构分为三类:编码器(Encoder-only)、解码器(Decoder-only)、编码器-解码器(Encoder-Decoder-only)

1.Encoder-only模型

​ 这些模型通常用于理解任务、文本分类、命名实体识别等

​ 特点是每个token都能那个看到整个序列(双向注意力)

​ 代表模型:BERT、RoBERTa、DistilBERT等

​ 个人理解:对于像文本做embedding和上述提到的整个文本句子分类,这些都比较关注整个语句的特征,但并不在意处理这个文本的每个token的顺序,因此优点在于可以提取出全局双向的文本特征,以及可以并行处理每一个token。

2.Decoder-only模型

​ 这些模型一般用于生成任务、文本生成等

​ 因为decoder模块使用的是mask_multi_self_attention,而其特点就是,在预测下一个token之前,只知道前面token的信息,以自回归的方式工作,根据输入的整个序列生成一个token,然后添加到输入序列中,再生成下一个token。

​ 代表模型:GPT、ChatGLM、LLaMA、Bloom

​ 个人理解:这类模型主要做的任务特点是,文本的token是在意其token顺序的,并且每次处理token,需要依赖前一次的状态,有点类似于LSTM这类时序模型。

3.Encoder-Decoder模型

​ 这类模型通常用到 Seq2Seq,如机器翻译、文本摘要

​ Encoder部分处理输入序列,Decoder部分以自回归的方式输出序列。同时Decoder还会使用交叉注意力(Cross-Attention)来使用编码器的输出。

​ 代表模型:T5、BART、M2M-100等

​ 个人理解: 专注于文生文,既要完整提取输入文本的全部特征,又要以自回归的方式生成一段相关的文本。所以既利用了输入文本的主要特征,又结合输入文本+已预测token的特征,来预测最终的输出。

KV Cache

1.推理生成的两个阶段

​ 整个推理流程可以分为两个阶段:

1.prefill阶段(预填充阶段):该阶段属于计算密集型操作(因为要并行计算大量token得到kv Chache)。模型并行处理输入序列的所有token,生成相应的KV Cache,并输出第一个预测的token。

2.Decode阶段(解码阶段) :该阶段属于内存访问密集型操作(只需要用上一个预测的token计算Q,K,V,前文信息用KV Cache,需要大量访存)。以自回归的方式依次生成后续的token。

2.prefill阶段流程

image-20251014112943392

image-20251014150711757

​ 根据全部的token计算,Q,K,V矩阵。最后Q*K^T,再做mask+softmax,得到注意力矩阵,这个矩阵是n*n大小,表示每个token对自己和它之前的token的关注程度,最后和V相乘,相当于做加权求和,得到一个n*dim(dim为隐藏层大小)的上下文向量,在最后一个decoder block只取QKV output的最后一行,将这一行用线性层处理,映射到vocab大小的维度,并且做softmax,得到logits概率,最大概率的token被选中(greedy算法)。

3.Decode阶段

image-20251014151656723

​ 可以看到,t3属于是prefill生成的第一个token,它不需要带上t0-t2再去和W_Q,W_K,W_V做计算,只需要自己与其做计算,再和之前计算好的K矩阵拼接(即K Cache),然后得到一个QK矩阵,该矩阵表示当前token对它以及它之前生成的token的注意力(注意这个矩阵每生成一个token,就会加长),再和矩阵V相乘,同样用到V Cache,得到最终得QKV输出,经过FFN和Add&Norm层处理后,作为下一个decoder block的输入,最后一个输出经过映射到vocab维度,并softmax选取token。

这里笔者开始有两个疑问,解决后在这里记录一下

1.首先为什么有KV Cache,而没有Q Cache

​ 通过计算过程可以发现,在decoder阶段,我们只关心每次最后输出的一个token得到的Q向量分别和K,V矩阵做计算,而并不关心之前已经计算过的token对应的Q向量,因此不需要。

2.为什么没有Q Cache ,但是prefill阶段,每一个decoder block里面都要计算一个完整的Q矩阵,而不是只关注最后一个token对应的Q向量

​ 这个问题其实需要注意,在decoder阶段,每一个decoder block都会用到之前的k v cache,而可以发现,这些k v cache的计算,需要一个完整的QKV output,而若要得到一个完整的QKV output,则Q矩阵必须包含所有token对应的Q向量,即一个完整的Q矩阵,因此预填充阶段,其实也是对k v cache的预填充。