An Overview of Transformer Models#

理解 Transformer LLM 行为的最常见图景是将其视为一个软件系统,该系统接收文本并生成响应文本。一旦在足够大的高质量数据集上训练出足够大的文本输入-文本输出模型

NeatReader-1744443899997

该模型并非一次性生成全部文本;实际上它是一次生成一个令牌。

NeatReader-1744443962742

在每个令牌生成之后,我们通过将输出令牌附加到输入提示的末尾来调整下一个生成步骤的输入提示。

NeatReader-1744443965734

在机器学习中有一个特定的词用于描述那些利用其早期预测来做出后期预测的模型(例如,模型的第一个生成的标记用于生成第二个标记)。它们被称为自回归模型。这就是为什么你会听到文本生成 LLMs 被称为自回归模型。这通常用于将文本生成模型与像 BERT 这样的文本表示模型区分开来,BERT 不是自回归的。

The Components of the Forward Pass 从前传递看组件#

大致上分为

  • Tokenizer:分词器
  • Stack of Transformer: 一组 Transformer 块
  • LM Head: 模型头(本身就是一个简单的神经网络)

NeatReader-1744444308851

Phi3ForCausalLM(
  (model): Phi3Model(
    (embed_tokens): Embedding(32064, 3072, padding_idx=32000)  // Tokenizer.  它有 32,064 个令牌,每个令牌的向量大小为 3,072
    (embed_dropout): Dropout(p=0.0, inplace=False) // 丢弃层
    (layers): ModuleList(
      (0-31): 32 x Phi3DecoderLayer(  // 32 个 Transformer 块
        (self_attn): Phi3Attention(    // 注意力层
          (o_proj): Linear(in_features=3072, out_features=3072, bias=False)
          (qkv_proj): Linear(in_features=3072, out_features=9216, bias=False)
          (rotary_emb): Phi3RotaryEmbedding()
        )
        (mlp): Phi3MLP( // 多层神经网络
          (gate_up_proj): Linear(in_features=3072, out_features=16384, bias=False)
          (down_proj): Linear(in_features=8192, out_features=3072, bias=False)
          (activation_fn): SiLU()
        )
        (input_layernorm): Phi3RMSNorm()
        (resid_attn_dropout): Dropout(p=0.0, inplace=False)
        (resid_mlp_dropout): Dropout(p=0.0, inplace=False)
        (post_attention_layernorm): Phi3RMSNorm()
      )
    )
    (norm): Phi3RMSNorm()
  )
  (lm_head): Linear(in_features=3072, out_features=32064, bias=False) // lm_head 接收一个大小为 3,072 的向量,并输出一个与模型所知令牌数量等效的向量。该输出是每个令牌的概率得分,有助于我们选择输出令牌。
)

Parallel Token Processing and Context Size 并行处理#

NeatReader-1744444816196

当前的 Transformer 模型对于它们一次可以处理的令牌数量有一个限制。这个限制被称为模型的上下文长度。一个具有 4K 上下文长度的模型只能处理 4K 个令牌,并且只会有 4K 个这样的流。

NeatReader-1744444953342

每个令牌流都以一个输入向量(嵌入向量和一些位置信息;我们将在本章后面讨论位置嵌入)开始。在流的末尾,另一个向量作为模型处理的结果出现

你可能会想,如果我们除了最后一个 token 的输出之外丢弃所有 token 流的输出,为什么还要经历计算所有 token 流的麻烦呢?答案是,之前流的计算是必需的,并用于计算最终流。是的,我们没有使用它们的最终输出向量,但我们在 Transformer 块的注意力机制中使用了早期的输出(在每个 Transformer 块中)。

从图上看,实际上之前的流的数据是被丢弃的,单实际上应该是用到了,在 Transformer 里面。

Speeding Up Generation by Caching Keys and Values 通过缓存键和值来加速生成#

NeatReader-1744445120428

在生成第二个标记时,我们只需将输出标记附加到输入中,并通过模型进行另一次前向传递。如果我们赋予模型缓存先前计算结果(特别是注意力机制中的一些特定向量)的能力,我们就不再需要重复先前流的计算。这次唯一需要的计算是针对最后一个流。这是一种称为键和值(kv)缓存的优化技术,它为生成过程提供了显著的加速。

Inside the Transformer Block#

一个 Transformer 块 通常包含

  • attention layer: 注意力层
  • feedforward layer: 前馈层: 一个给出前馈神经网络直觉的简单示例是,如果我们将简单输入“肖申克”传递给一个语言模型,期望它会生成“救赎”作为最可能的下一个单词(参考 1994 年的电影)

NeatReader-1744445322359

“The dog chased the squirrel because it” 为例子,对于模型要预测“it”之后的内容,它需要知道“it”指的是什么。它指的是狗还是松鼠?在经过训练的 Transformer LLM 中,注意力机制做出了该决定。注意力将来自上下文的信息添加到“it”标记的表示中。

这个举了一个例子:注意力机制在该位置的输入向量上运行。它将来自上下文的相关信息合并到作为该位置输出而产生的向量中。

NeatReader-1744445602015

注意力机制涉及两个主要步骤:

  • 一种对每个先前输入标记与正在处理的当前标记的相关性进行评分的方法(在粉色箭头中)。
  • 使用那些分数,我们将来自各个位置的信息组合成一个单一的输出向量。

NeatReader-1744445664327

comments powered by Disqus