Transformer
# Transformer
# 背景回顾
我们准备做的事情:接收一段文字,预测下一个词。
transformer第一步要做的事是将每个token关联到一个称为嵌入向量的高维向量。(初始的token嵌入实际上是没有上下文参考的查找表)
transformer的目标是逐步调整嵌入向量使它们不单单编码单个词,还能融入更丰富的上下文含义。
transformer的核心-注意力的目的就是把一个泛型嵌入向量比如“塔”,它前面如果有个“埃菲尔”,那么就应该有个机制来更新这个向量,使其更具体地指向埃菲尔铁塔的方向,新的向量也许还会关联上巴黎 法国 与 钢铁制品等。这个机制就是注意力机制。
# 注意力模块
attention精细了一个词的含义,还允许模型互相传递这些嵌入向量蕴含的信息。
所有向量流经网络后,经历了许多层的注意力模块。此时预测下一个token的计算过程,完全基于序列中最后一个向量
举例来说,你几乎输入了整本推理小说,从头输入到快结尾的'因此,凶手是……'这里结束,如果模型要准确预测下一个词,该序列中的最后一个向量,即‘是’的嵌入向量,必须经过所有注意力模块的更新,也就是要设法编码整个上下文窗口中与预测下一个词相关的所有信息
具体计算过程
以一个例子来讲:输入包括以下短语“一个毛茸茸的蓝色生物漫步于葱郁的森林”。
作为铺垫,先了解单头注意力机制
# 单头注意力机制:
每个词的初始嵌入是一个高维向量,只编码了该单词的含义,和上下文没有关联
初始向量内的元素足以说明这个词是什么和他在文中的位置,用

# Query矩阵
查询矩阵将嵌入空间中的名词映射到一个较小的查询空间中的某个方向,用来表示“寻找前置形容词”,类比于嵌入空间上的某个向量能表示某个词。
再代入到上面那个公式,相当于,生物* 查询矩阵 = 我前面有形容词吗?(等式为什么成立?答:在一次次的训练中拟合的) 即提出了这样的一个问题,后面会和其他矩阵配合回答从而将上下文联系起来。
# Key矩阵
键矩阵同样会把嵌入向量映射到一个低维空间,意为答案(这个词的属性),当键向量与查询向量方向对齐时,就能认为他们是相匹配的。
# 注意力模式
为了衡量每个键与每个查询的匹配程度,要计算所有可能的键--查询对之间的点积,值越大,说明越匹配。在例子中,毛茸茸的和蓝色与生物的点积就会比较大,即 毛茸茸的 和 蓝色 的嵌入注意到的 生物 的嵌入,其他值相乘就是比较小或者负的,意思就是这两个词互不相关

这些分数是用来加权求和的,权重就是相关性,所以要对这些分数softmax,使其形成类似于概率分布。称为:注意力模式

原文给出的公式:
这里Q和K包含了所有的查询向量和键向量,等式右边分子代表了所有可能键-查询对直接点积的网络。除以键-查询空间维度的平方根是为了维持数值稳定性。softmax是对每列进行的计算。V后面讲。
在训练过程中,对给定示例文本跑模型的时候,模型会根据正确预测出下一词的概率高低来进行奖惩,并稍微调整各个权重。效率更高的方式是,让模型同时预测每个初始token子序列之后所有可能的下一个token。

即对于示例文本,它可以同时预测‘生物’的下一个词和‘葱郁’的下一个词,这样就可以做到一个训练样本就能提供多次训练机会。
对于注意力模式而言,这意味着不能让后词影响前词。也就是说,注意力模式表格的左下方,这些代表后方token影响前方的位置能被强制变为0,一般的做法就是在softmax之前把他们设置为负无穷,这样在归一化之后就都是0了。这就是掩码。
注意力模式表格大小等于上下文长度的平方,这就是为啥上下文长度会成为大语言模型的巨大瓶颈。
得到这个注意力模式表格后,下一步就是更新嵌入向量
# 更新嵌入向量
把各个词的信息传递给与之相关的其他词。
例如,想办法让‘毛茸茸的’的嵌入改变‘生物’的嵌入。想办法使其移动到12288多维度嵌入空间的另一个方向上,从而更具体地代表毛茸茸地生物。具体是通过v矩阵实现的。

# value矩阵
value矩阵就是用来更新嵌入向量的。
这个值向量也就是要给后面的嵌入加的值,即生物的嵌入向量加上毛茸茸的值向量就能给后面这个词赋予更多的含义,注意,值向量与上述QK向量不同,它是在高维空间。
对于上述值向量的公式,可以理解为,如果这个词需要调整目标词的含义,那么要反映这一点就需要对目标词嵌入加点东西,那么具体怎么加呢?这就涉及到注意力模式中的表格了,对每个词得到的值向量乘以对应列的权重再求和,就是最终目标词需要加的值。

上述所有内容,就是单头注意力机制。这个过程就是由三个填满了可调参数的矩阵实现的,即Q-K-V矩阵。其中,V矩阵的输入输出都是高维的嵌入空间,因此size实在太大,实际上的方法是把这个12288 * 12288 的矩阵拆成两个 12288 * 12288 的矩阵。
一个注意力头有4个12288 * 128的矩阵,所以一个注意力头就有630万个参数。GPT-3有96个注意力头,一层大约有6亿个参数,GPT-3有96个不同的层,所以最终的参数大约是580亿个。(每个层的输入是前一个层改变后的词嵌入向量,所以96个层,每个层中96个头参数都不一样。)
# 多头注意力机制
就是有多个Q-K-V矩阵,产生多个注意力模式和值向量。注意,注意力头们是并行工作的,也就是说,对于上下文中的每个token,每个头都会给出一个要加入到该位置嵌入值中的变化量。transformer要做的就是把各个头给出的变化量加起来,然后给该位置的初始嵌入加上这个加和,这个总和,就是多头注意力模块输出的一列。
这里3b1b讲的和论文里的似乎有点区别,按论文的说法,嵌入值在进入注意力模块初始时计算出三个12288维度的Q-K-V向量,在分别投影到96个维度为128的子维度去计算注意力表格,注意这里输出的V向量也是128维,也就是说每个头输出的ΔE也是128维的,所以还需要把他们再拼接起来再乘以一个12288 * 12288的矩阵(用来全局整合,将不同头的信息进行混合,从而允许模型学习如何将不同头的注意力结果组合起来,能增强模型的表达能力)才能得到与嵌入token相同维度的最后的ΔE
# MLP模块
一个训练好的大语言模型,已经记录了人类的大部分知识。那事实在LLM里的存在形式到底是什么样的?一个普遍的结论是,各种事实信息似乎都存在于多层感知器(MLP)中。
MLP的计算相对简单,总结起来就是一对矩阵乘法中间夹杂着一些非线性变换。在这一层中,每个向量都是单独处理的,不会和其他向量有交集。
依然以一个例子来讲:“乔丹会打篮球。”
# MLP的内部
首先看mlp的输入,即注意力模块的输出,是融合了上下文信息的token序列。预期是经过mlp能得到相同维度的token序列,包含了和这个token(比如迈克尔乔丹)相关的一系列信息(比如篮球,公牛队,黑人等等)。
# 提问期
对输入token乘以一个巨大的矩阵(49152* 12288),我们把它称为
我们假设

现在做第二个假设,

GPT-3
# 激活函数
上述操作是纯线性的,但语言是个非常非线性的过程。引入激活函数能使系统提高拟合能力,在不同语境中学习相同词语的不同含义。在transformer中的表现就是通过激活函数筛选出足够活跃的神经元再传递给下一层。
# 回答期
对经过激活函数的神经元乘以一个12288 * 49152的矩阵

# 叠加效应
事实上,单个神经元几乎无法独自代表一个干净的特征比如迈克尔乔丹。

因此这里提出叠加效应,它的基本思想是如果你有一个n维空间,并且我想用方向表示许多不同的特征,所有方向都是相互正交的,这样的话我只能定义n个特征。
例如三维空间只能定义三个比如身高体重年龄,然和一个坐标/方向都是在描述这个东西多大了多高多重,而无法描述它/他/她是哪国人?喜欢什么等等。
具体定理来自Johnson–Lindenstrauss定理,它描述了随着空间维度的增加,我能放下的向量数会指数级增长。
在transformer中的表现是,当维度足够高时,随机的向量间几乎也能做到点积为0,也就是说它俩几乎没关系。
回到上述问题,虽然只有49152行/列,但是通过他们的排列组合实际上几乎能有无限种可能,每一种排列组合包含的信息也是很丰富,这就解释了为什么llm表现地如此灵活智能。
总结起来,MLP的作用就是接收包含上下文的token序列,对每个token进行增强,赋予更多信息。
# 原视频部分评论(辅助理解)
mlp的第一层,即投影到更高维度空间层的神经元会告诉transformer输入的嵌入向量与某个特定方向的对齐程度;最后一层,即把高维度投影回来的神经元会告诉transformer如果该神经元活跃,那结果会被添加到什么。
最终的词嵌入通过注意力机制进行上下文增强,并通过多层感知器(MLP)向下一个词元的方向偏移,使其成为一个更贴近下一个词元向量的表示。这种增强并向下一个词元偏移的词嵌入随后被映射到词汇空间,其中softmax函数生成所有可能词元的概率。
我们可以用参数组合来编码“概念”,而不仅仅是用单个参数。为了更简单地理解,我们假设有参数A、B和C来编码概念,并且它们只能取0或1的值,分别表示文本是否包含某个类别概念。 (也就是说,这更像是“是迈克尔·乔丹”与“不是迈克尔·乔丹”之间的区别,而不是像“老”或“高”这样具有不同层次的概念。)
起初,人们可能会认为只能用 A、B 和 C 来编码 3 个想法/概念。但即使是初级程序员也会意识到,仅仅使用 0 和 1,实际上就可以用这 3 个参数编码 8 个不同的想法。你可以单独使用 A、B 或 C。但你也可以使用 A+B(即 A 和 B 都等于 1)、B+C、A+C 或 A+B+C。或者,你也可以让所有这些值都等于 0。因此,A 可以是“宇航员”,B 可以是“忍者”,A+B 可以代表“山羊”。只要这三个概念不同时出现,A+B 就可以代表与 A 和 B 本身完全不同的事物。这就是叠加,非常非常基础的层面。所以,一个 3 参数的空间可以表示 8 个概念。
但这仅仅是个开始,因为我们并不局限于 0 和 1。如果我们允许负值呢?也许 A=1 代表“宇航员”,而 A=-1 代表“忍者”。只要没有宇航员同时也是忍者,这种编码方式就可行。这意味着我们可以在 A、B 和 C 中存储更多潜在的概念。正如视频中所示,我们还可以为不同的参数赋予权重。因此,A+B 可能代表一种含义,2A+B 可能代表另一种含义,A+2B 又可能代表另一种含义。所有这些都是不同方向的不同向量,因此即使只有 2 或 3 个参数,理论上也可以仅通过权重和不同的值来存储数千个不同的概念。通过以这些不同的方式组合几个不同的参数(例如,2A+3B+5C),我们可以得到一个“叠加”概念,它与 A、B 或 C 单独表示的任何含义都不同,如果它们本身有任何含义的话。
概念越“稀疏”(也就是说,如果它们与其他概念没有潜在的重叠),即使参数不多,信息“存储”的效率就越高。
问题在于,即使是罕见的概念也常常与其他概念存在一些重叠。罕见情况时有发生,逻辑学习模型(LLM)需要为此做好准备。例如,假设你有几个参数,可以映射所有名叫迈克尔的名人。迈克尔·乔丹是一个方向,迈克尔·杰克逊是另一个方向,迈克尔·道格拉斯又是第三个方向。但是,如果你遇到一些提到名叫迈克尔的著名运动员的文本,有时是迈克尔·乔丹,有时是迈克尔·菲尔普斯呢?人工智能算法甚至可能因为这些名字出现在关于体育、纪录保持者等的文章和文本中,而在空间上将它们更紧密地归为一类。
乍一看,“迈克尔·乔丹”可能是 2A+B,“迈克尔·菲尔普斯”可能是 3A+B 之类的,但这可能会导致混淆和错误。这两个概念都包含一定量的 A 和 B,这会导致 LLM 计算中的“干扰”,从而可能导致误判或其他错误。或许在某种罕见的情况下,宇航员其实是一位养了山羊的忍者。所以,或许把太多概念“存储”在少数几个参数中并非明智之举。
不过,格兰特在视频中指出,这些问题在高维空间中会变得不那么突出。只有两三个参数的叠加态似乎很快就会变得“拥挤”。但拥有成百上千个参数的叠加态则截然不同。
衡量概念间“干扰”程度的一个指标是它们是否“正交”。也就是说,它们在整个空间中是否呈 90 度角?如果它们正好是 90 度角,则完全不会相互干扰,这是理想情况。但这样一来,我们就又回到了只有 A、B 和 C 这三个轴,而它们只能表示三个概念的情况。但如果我们只允许少量干扰(算法在多层计算过程中会忽略这些干扰)呢?
这就是视频中 89 度到 91 度之间向量对数量的意义所在。如果你随机选择两个二维或三维向量,它们“近似正交”(角度在 89 度到 91 度之间)的概率只有大约 1%。如果它们真的正交,干扰程度会非常小,在 LLM 中几乎不会造成问题。
但是,如果空间维度达到 100,两个随机向量角度在 89 度到 91 度之间的概率约为 14%。高维空间很“特殊”,所以你只能相信我,在高维空间中选择的向量不太可能产生显著干扰。对于 1000 维空间,这个概率会超过 40%。对于 10,000 维空间——本视频中许多向量和矩阵的维度——这个概率超过 90%。也就是说,如果你在 10,000 维空间中随机选择两个向量,它们“近似正交”的概率远大于 100%,因此不会产生显著的相互干扰。
这使得在高维空间中存储更多概念成为可能。即使没有 Grant 在视频中介绍的优化方法(即试图让 10,000 个向量在 100 维空间中整体上更正交),在这样的空间中,即使是随机向量也很可能近似正交。因此,在约 10,000 维的空间中,“迈克尔·乔丹”和“迈克尔·菲尔普斯”以及数百万其他概念更容易近似正交,从而可以比在低维空间中更好地存储,减少相互干扰。