Koalablog

LLV Visualization 拆解

2025-07-24

https://bbycroft.net/llm

基于 Nano GPT 的可视化推理过程,模型得到的训练是对字符串进行排序

步骤一:Embedding

这一步的输出是切分好的 Token 数组,对于现代 LLM 我们可以认为他是 Prompt,也可以是 LLM 的输出结果的前半部份, LLM 经过一系列运算会得到这一系列 Token 对应的最大概率下一个Token。

输入 Token 数组(长度为 $C$,这是个超参数)的每一个元素会得到 Token 的编码值和当前的索引值(Position)。由编码值计算出 Token Embed 向量(长度为 $T$ ,这个 $T$ 的实际含义是时间,我们先简单理解为次序),由索引值计算出 Position Embed 向量(长度为 $T$ ),然后将这两个向量相加得到真正的输入 Input Embed 矩阵($size = C \times T$)。

步骤二:归一化

这一步将输入的 Input Embedding 矩阵的每一列归一化,所谓归一化,在 Nano GPT 当中就是将这一列的均值调整为 0,方差(标准差)调整为 1。具体拆解如下:

  1. 计算出每一列的均值 $E[x]$ 和方差 $Var[x]$
  2. 对 Input Embedding 的每一个元素都在原位进行如下计算,这里的 $\epsilon = 10^{-5}$ ,主要作用是防止除零。减去均值除以标准差,然后乘以一个经过学习的权重,加上一个偏置值,归一化就完成了。$$\frac{x - E[x]}{\sqrt{Var[x]} + \epsilon } \cdot \gamma + \beta$$

步骤三:Self Attention

自注意力层也许是 Transformer 和 GPT 的核心,这一步会让 Input Embedding 中的列相互交流,而在这之前,每一列都是独立存在的。自注意力层由多个头组成(Nano GPT 有三个),可以先只看一个。

第一步,我们要从 Input Embedding 的每一列 T 中生成三个向量,这些向量是 Q、K、V 向量。生成这些向量的步骤是做向量乘法,每一个输出单元是输入向量的线性组合。例如生成 Q 向量时,我们将 Q 权重矩阵的每一行和 Input Embedding 的当前列(T)相乘,得到一个向量,再加上一个 Q 偏移量(Q Bias),就得到了 Q向量。Q、K、V 向量均使用这种方法生成。

生成完成之后,我们需要考虑如何处理 Q(Query)、K(Key)、V(Value)。从名称上来看,我们也许可以将 Q(关键字)应用于 K(字典),得到 V(最终值)。自注意力层基本上也是这样,不过需要通过权重来实现:将 Q、K 取点积,然后归一化处理,与 V 相乘,再将结果相加,得到结果。具体如下

  1. 将当前 Q(例如第 6 列,$t=5$)和之前所有列的 K 计算点积,除以$\sqrt{A}$,其中 $A$ 是 QKV 向量的长度。结果将存储到注意力矩阵的第六行($t=5$)当中,点积可以衡量向量相似度,相似度低则点积很大,相似度高则点积很小或者为负;除以长度则是为了避免很大的值在归一化后占据主导地位。
  2. 对生成的注意力矩阵做 softmax 操作,规范化到总和为 1
  3. 取注意力矩阵 softmax 后的结果,每一个元素与对应的 V 向量逐一相乘,得到输出的 V。

以上就是单个注意力头的处理过程,其主要目标就是通过 Q 向量与当前和过往所有的 K 向量进行比较来查找与 Q 相关的信息,然后从 V 中提取出这部分信息

步骤四:Projection

自注意力层处理完成之后,从每个头中得到了输出,一些混合了 Q、K 向量影响的 V 向量。为了组合这些输出,我们将他们堆叠在一起,例如从 3 个头输出的长度为 $A = 16$ 转换为 1 个长度为 $C = 48$ 的向量。也就是说,在 GPT 中,一个头内的向量长度等于 $C / N$ ,$C$ 是输入 Input Embedding 的向量长度, $N$ 是头的数量。这样,当我们将它们的结果组合在一起时,就得到了原来的长度 $C$。

在 Projection 层中,我们按列矩阵(权重矩阵)和头向量的乘法,添加一些偏置,得到初步结果。再将初步结果与最早的 Input Embeddding 求和,这一步被称为残差连接(residual connection),这一步在深度神经网络中同样很关键。

步骤五:MLP

MLP(multi-layer perceptron 多层感知机,一种前馈神经网络 Feed Forward Neural Network) 是 Transformer 的后半部份,在 Nano GPT 当中是一个具有两层的简单神经网络。在进入 MLP 之前同样需要做一遍和之前[[LLM Visualization 笔记#步骤二:归一化]]一样的归一化操作,均值、方差和偏移。

在 MLP 中,我们将长度为 $C = 48$ 的列向量进行下面四个步骤:

  1. 将 MLP 权重矩阵(包含偏置行向量的线性变换矩阵)应用于归一化之后的输入,得到一个长度为 $4 \times C$ 的 MLP 矩阵;
  2. 将 GELU 激活函数应用于 MLP 矩阵的每个元素;
  3. 将 MLP Projection 权重矩阵(另一个包含偏置列向量的线性变化矩阵)应用于上一步的结果,得到和原先尺寸一致的 MLP 结果($T \times C$);
  4. 和之前的自注意力层一样,将 MLP 的结果以元素为单位与上一层的结果相加(残差连接),得到最终结果。

MLP 完成之后,Transformer 的任务就结束了。Transformer 是任何一个 GPT 模型的主要部分,并且会被多次重复,一个块输出并输入到下一个块,并继续进行残差连接。

我们很难确切地说出每层在做什么,但有一些大致的想法:早期的层倾向于学习较低层次的特征,后期的层则学会识别和理解更高层次的抽象概念。例如在自然语言处理中,较低的层可能在学习语法规则、句法、简单的词语关联,较高的层可能会捕捉更复杂的语义关系、篇章结构和上下文语义。

当然这里需要强调一下,GPT 是基于 Transformer Decoder 的模型,所以上述的 Transformer 只是 Decoder 的部分。

步骤六:Softmax

Softmax 不但是自注意力层的一部分,也将在模型的最后部分出现。其目标是获取一个向量并将其值规范化,使它们的和为1.0。但 Softmax 不是简单的将每个值除以向量的总和。

每个值首先需要被指数化,然后将指数化的值除以指数化值的总和,这可以保证值的总和为 1.0。由于所有指数化的值都是正数,所以结果必然在 0.0 和 1.0 之间;这就是 softmax 的基本流程。$$\frac{\exp(x_i)}{\sum\exp(x_i)}$$ 这里有个小问题,如果输入的值($x_i$)比较大,那么指数值也会变大,如果将一个大数除以另一个大数,可能导致浮点数运算出现问题,这里我们需要利用 softmax 的一个特性:如果给所有输入值加上一个常量,结果将保持不变。因此,我们可以给输入值($x_i$)减去向量中最大的数($\max(X)$),这样可以确保最大值是 0.0,softmax 在数值上保持稳定。

在自注意力层当中,softmax 操作的输入向量是矩阵的一行。为了操作方便,我们创建了一个中间矩阵,用于存储一些便于运算的结果,例如向量的 $\max(X)$ 和 $\sum\exp(x_i - \max(X))$。

为什么叫 “softmax” 呢?因为存在一个硬核版本是 argmax,他的结果是找到最大值,设置为 1.0,并将其他值赋为 0.0,相比之下 softmax 会更 ”soft“。由于 softmax 是用了指数运算,最大值会被强调并接近 1.0,同时在整个输入值域上保持概率分布,允许捕捉最有可能的选择,保留其他选项的可能性。

因此,softmax 操作会被 QKV 的注意力层使用,还会在最后的输出部分使用。

步骤七:Output

最后的 Transformer 结果经过一次归一化处理,然后再经过 LM Head 权重矩阵的线性变换(这次没有偏置值),目标是将列向量长度从 $C$ 变为 $nvocab = 3$,nvocab 实际上是词汇表的长度。这实际上为每个词生成了一个分数,这个分数被称为 logits。

logits 来源于 log-odds(对数几率),也就是每个 Token 的几率的对数。之所以是 log odds,是因为 softmax 操作会将值进行指数运算以转换为概率值(odds)。

softmax 之后,我们得到了模型分配给每个单词的概率。在这个特定的模型当中(nano-gpt),他实际上已经学会了如何排序三个字母,所以概率结果偏向正确答案。

我们一般会让 LLM 随着时间步进,此时,使用最后一列(最后一个 Token 对应的列)来确定添加到序列的下一个 Token。例如,输入了 6 个,使用第六列的概率。这一列的结果是一系列的概率值,我们需要从中挑选一个作为序列中的下一个。一般来说,我们根据概率值来随机选择一个 Token,概率更高的标记更容易被选中。

这里有一个超参数是 Temperature,较高的温度会使得分布更均匀,较低的温度可以使分布集中在概率更高的标记上。Temperature 的生效方式是在 logits 应用 softmax 之前先除以 Temperature,让所有概率数字变得更接近。

总结

回头来看,Transformer Decoder 由多头自注意力层和前馈神经网络层组成,主要的能力是根据历史的 Token 串预测下一个 Token 在字典中索引的概率。自注意力层的功能是从 Embedding 向量通过线性变换拆分出 QKV 三个向量,Q、K 向量做点积再与 V 相乘。我们可以在推理过程中看到大量的线性变换矩阵,这些矩阵大多是在训练过程中产出。在使用标注数据不断训练的过程中,神经网络会不断更新这些矩阵,以拟合训练数据的标注。