• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

WIPGPT 3 模型结构

武飞扬头像
xunhe
帮助1

背景

从 ChatGPT 发布以后,我们似乎看到了 AGI(通用人工智能)的曙光,不管什么样的任务,从写文章到写代码,甚至是一些带推理和创意性的思考,基本上有问必答,虽然仍然有幻觉的问题,但总体来说质量非常高,极大的提升了我们的生产力。本文将结合网络上的参考资料,对已经公开的 GPT3 的基本原理做比较粗略的分析,目标是做一个心里有谱的“调包侠”🐶。

语言模型原理

虽然表现出了通用人工智能的特性,但从原理上来说,ChatGPT 其背后的 GPT3.5、GPT4 只是一个语言模型,它的基本工作模式(推理过程)是,给定一串输入的文本,预测下一个输出的字符,再结合输出的字符与输入的文本中作为新的输入,循环往复,直到输出的是结束符为止。使用数学的等价表述就是,给定一个词典 V={猫,狗,机器,学习,语言,模型,...}V=\{猫,狗,机器,学习,语言,模型,...\}ω1⋯ωn∈V\omega_1\cdots\omega_n\in V,计算 P(ωi∣ω1,ω2⋯ωi−1)P(\omega_i | \omega_1, \omega_2 \cdots \omega_{i-1}) 的条件概率。

如何高效合理地计算这个概率呢?随着时代的演进,先后出现了 N-Gram 模型、前馈神经网络模型、循环神经网络模型(大名鼎鼎的 RNN)等,直到 Transformer 的横空出世,大语言模型开始产生了质的变化(TODO: 补充一下各个模型的大概特点和限制? 参考链接)。

为什么如此简单的原理可以实现这么惊艳的效果呢?信息压缩吗?

神经网络基础

在开始介绍基于 Transformer 的 GPT3 架构之前,我们需要先了解什么是神经网络。我们从一个最简单的象限分类的场景出发:假设已知四个点坐标和它们所处的象限信息(如下图所示),给定一个未知点坐标(2,2),如何预测它所处的象限,即正确的将它分到 I - IV 这四个类别中。

仅做示例,实际上这个分类边界我们已经知道了。在开始之前,推荐大家先回顾一下线性代数的基础 链接

学新通

我们需要构建一个最简单的两层的神经网络,输入是一个 1x2 的二维矩阵 X=[x,y]X = [x,y] ,输出是一个 1x4 的表示点落在各个象限的概率的矩阵 [PI,PII,PIII,PIV][P_I,P_{II},P_{III},P_{IV}] (输入和输出的矩阵形式取决于我们的任务),这个网络的结构是这样的:

学新通

可以将隐藏层形象的理解为 50 个神经元(具体的神经元个数可以根据任务自行设定),每一个神经元做的事情,就是将输入的特征做一次线性的映射得到输出的值 h1=(x,y).w⃗1 b1h_1=(x,y) . \vec w_1 b_1输入层映射到隐藏层整体可以使用矩阵乘法表示为:

H=X⋅W1 b⃗1H=X \cdot W_1 \vec b_1

其中 W1W_1 是一个 2*50 的权重矩阵,偏置 b1 是一个长度为 50 的向量。隐藏层映射到输出层也是同理,W2W_2 是一个 50*4 的权重矩阵:

Y=H⋅W2 b⃗2Y = H \cdot W_2 \vec b_2

如果从输入到隐藏层,隐藏层再到输出只是两次线性变换的话,根据线性代数的原理,多次线性变换是可以合并成一次的,这样的话,不管做几层神经网络,其实都是没有意义的。所以我们需要给隐藏层做一次非线性变换处理,即对隐藏层中的每一个值(标量),都通过一个非线性函数映射到新值,我们称它为激活函数,图中的 ReLU 就是一种激活函数,常用的激活函数的函数曲线如下图所示:

学新通

对于神经网络的推理阶段,上述的 X→YX \to Y 就已经能实现我们的目标了,Y 中最大的那个值就是概率最大的象限了。但是机器学习编程的目的,其实是为了从数据中学习,具体来说,我们需要通过训练过程来得到合理的权重矩阵和偏置向量(默认的权重矩阵、偏置都是随机初始化的)。

搭建好网络结构后,第一步是使用训练数据进行训练,然后才是用模型(网络结构 权重的 checkpoint)来推理,训练的流程可能和推理的流程有细微的区别,这个需要区分开来。

矩阵 Y 的结果可能是形如 [3,1,0.1,0.5] 的数字,为了能够对输出结果做更好的衡量,我们需要通过下面的公式把它转成概率分布:

Si=ei÷(∑ej)S_i = e^i \div (\sum e^j)

我们称这一层叫 softmax,通过 softmax 之后,我们得到了形如 [0.9, 0.05, 0.02, 0.03] 这样的概率分布。那么我们如何去衡量这个输出的好坏,从而实现我们的训练目的呢?比较直观的想法是,真实的概率分布其实是 [1,0,0,0],那么使用 1-0.9=0.1,这个数字越大,代表和实际情况偏离越严重。在实际使用过程中,我们会使用负对数来表示这个偏差,即 -log0.9=0.046。从函数曲线就可以看出来,概率越接近100%,损失就越接近0。这个就是交叉熵损失(Cross Entropy Loss)的计算方法。

学新通

得到损失函数之后,我们就可以通过反向传播去更新前置的每一个权重矩阵,反向传播公式的具体推导过程可以看这个教程。然后经过一轮一轮的迭代之后,我们就可以得到误差足够小,足以拟合我们任务场景的权重矩阵 偏置了。

TODO: 总结一下神经网络的定义。

GPT3 网络结构

理解了神经网络的基本概念,下面我们就可以逐层去拆解 GPT3 的网络架构(基本上就是对 Transformer 网络架构在语言模型场景的实践),学习大名鼎鼎的自注意力机制。这是来自论文《Attention Is All You Need》中的关于 Transformer 的架构图,咋一看肯定一脸懵逼,下面我们会分层去讲解其中的原理:

学新通

输入内容处理

还记得我们在语言模型这一节提到的,语言模型的基本原理是输入一个文本序列(Sequence),预测下一个输出的 Token。那么语言模型应该如何理解我们输入的内容呢,Transformer 又对这一过程做了什么样的优化呢?

Encoding

首先我们需要将输入的词转成神经网络可以处理的向量的形式,GPT 首先使用了非常好理解的 One-Hot 编码,即有一个 50257 长度的向量,除了第 i 位为 1,其它的位置均填充 0,通过这种方式可以记录一个拥有 50257 个词汇(GPT 使用的是 Byte Pair Encoding,实际上并不全是单词,而是文本里常出现的字符序列,比如 heroes、cap、es)的集合:

学新通

那么我们就可以把我们的输入编码成一个 2048*50257 的矩阵(GPT3 能处理的上下文长度为 2048,现在最新的 GPT 3.5 已经是 16K 了),其中暂未输出的内容使用空 <> 填充:

学新通

Embedding

One-Hot 编码虽然很好理解,但是 50257 的长度有点太大了,而且大量的 0 其实是在浪费空间,也并没有体现出 Token 与 Token 之间本身存在的一些关系,完全是离散的。为了解决这一问题,机器学习的一般做法是会使用一个权重矩阵,把高维的 One-Hot 编码映射为一个更低维的向量,同时也包含完整的信息。

Embedding 的一个形象的 case:三维的球面其实是二维的流形嵌入三维空间的结果,因为任何一个球面上的点都可以使用二维的经纬度来表达。

在 GPT3 里,它使用了一个 12288 维度的向量来表达每一个 Token,所以需要训练一个 50257*12288 的嵌入权重矩阵 WEW_E 来实现这一目的,最终得到一个 2048*12288 的输入矩阵:

学新通

Position Encoding

经过上两轮的处理,我们输入的序列已经成为了一个 2048*12288 的输入矩阵,但需要注意的是,在模型训练时,Transformer 架构会并行计算每一个 Token 的结果(TODO 实现方式没太看懂),而不是像传统 RNN 一样,每一个 Token 的输入都要依赖前一个 Token 的输出。这就要求每个 Token 的向量需要包含它所处的位置信息,并且需要有以下几点要求:

  1. 它能为每一个 Token 位置生成一个独一无二的编码
  2. 在不同长度的序列中,距离相同的 Token 之间的编码差值应该是相同的
  3. 模型应该有足够好的泛化性(DEF?),位置编码的值应该是有界的,不能出现位置编码的值把特征给盖过去的情况
  4. 位置编码应该是确定的

Transformer 非常聪明的提供了一种基于正余弦函数的位置编码方法,使用数学的表述,即对于我们 2048*12288 的输入矩阵而言,假设 t 表示在序列中的位置(1~2048),d 表示单个向量的维度(12288)那么位置编码 p⃗t∈Rd\vec p_t \in R^d 的定义为(注意,这里位置编码使用的是向量而不是一个普通的标量):

学新通

从第一行到第n行的位置编码向量可以图形化的表达为:

学新通

上面提到的 1、3、4 条件应该可以直观的感受到,第 2 点可以通过高中数学的和差化积公式来推导,具体推导过程可以参考 链接

通过给每一个输入的 Token 向量叠加上位置编码,每个 Token 就拥有了本身的特征信息 位置信息,就可以为后续训练时的并行计算做好准备了。

注意力层

从 Transformer 的网络结构可以看到,在经过向量化(Embedding)处理,累加位置编码之后,我们的输入就进入了多头自注意力层(Multi-Head Self Attention),我们会分别从注意力、自注意力和多头自注意力来逐步理解这一机制的大致原理。

注意力机制

提到注意力机制,必然会提到计算机视觉领域下面这张非常经典的图,这也非常符合我们人类的直觉:在有限的信息处理能力下,大脑会首先快速扫描一遍图像,获得需要关注的焦点,再对焦点投入更多的注意力,并忽略其他不重要的信息。

学新通

回到深度学习领域,它的目的也是从一堆信息中学习到关键知识。怎么做呢?假设我们有一个查询 Q(query,对应上面那个图的人类观察者),我们的目的是能够从数据 V (values)中获取到关键信息,那么计算的目标就是获取 Q 和 V 的相关度。如何计算呢?我们创建一个新的矩阵 K(keys)= V(一般数据都没有索引,可以让索引直接等于数据),对 Q 和 K 求相似度,再做一层 softmax 归一化,就得到了注意力权重矩阵,再使用注意力权重去乘上数据,就可以为关键数据提供更多的权重:

学新通

自注意力机制

相比于注意力机制,自注意力机制的主要差异就是 Q 的取值来源于数据,即 Q、K、V 均来源于输入,为了便于理解,我们下面使用一个简化的数据来描述 Transformer 处理自注意力的流程。

假设我们的输入只有 3 个 Token,每个 Token 使用一个 512 维的向量表示,我们的模型会学习三个 512512 的权重矩阵 WQ,WK,WVW_Q, W_K, W_V ,得到三个 3512 的新矩阵 Q=WQ⋅A,K=WK⋅A,V=WV⋅AQ=W_Q \cdot A, K=W_K \cdot A, V=W_V \cdot A ,对 QQKTK^T 使用矩阵的点乘求得余弦相似度:

学新通

学新通

再做一次 softmax 就得到了每一个 token 和其他 token 关系的 3*3 的权重矩阵,这个三乘三的矩阵的含义可以可视化的表达如下(线越黑代表越相关,没有连线代表不相关),即权重矩阵的每一行代表了该位置的 token 和其他 token 的关联关系:

学新通

下面,我们使用这个注意力权重矩阵再点乘上我们的输入矩阵,就可以得到包含了每一个位置 Token 和其他 Token 的注意力信息的新的 Token 向量(TODO 这也是能并行训练的基础,还要再理解一下)。下面这个图假设注意力矩阵只有 1 和 0,即每一个 Token 只和另外一个 Token 相关,得到的结果是第一个 Token 仍然是自身,第二和第三个 Token 却完全交换了一下顺序(TODO 这个的进一步解释)。

学新通

多头注意力

在实践中,GPT 使用了多头注意力,简单来说,就是把上一环节输入的向量做了一次切分,使用切分后得到的矩阵分别做自注意力计算(即对输入矩阵做纵向的分割后独立计算),再把得到的矩阵纵向拼接起来。输出仍然是和单头的自注意力计算是一样的。按照论文的说法,多头保证了 attension 能注意到不同子空间的信息,捕捉到更加丰富的特征信息。(TODO: 说实话,对 Token 向量的纵向分割是把信息放入多个子空间这个说法没有理解,来个好心人教教我……)

学新通

注:上图中把每一个子空间的权重矩阵都划到每个头内部了,实际上是在外层计算后直接分割到 96 个头里面,只用学习三个权重矩阵。

前馈神经网络层

图中的 Feed Forward 就是我们在神经网络基础里面讲到的最常见的带一个隐藏层的神经网络,拿到输入,乘上学习的权重,加上学习的偏置,再做一次激活,就得到了输出结果。具体的可以回去看上面的内容。

学新通

Add & Norm 层

从架构图中可以看到,在多头注意力拼接输出和前馈神经网络输出后,都有一层 Add & Norm 层,这个逻辑非常简单,就是拿原始的输入,再直接矩阵加上输出的内容,得到新的输出,然后再做一次正则化后输出到下一层中。(这是从残差网络问世以来深度学习的常见做法,可以有效的解决深度神经网络的退化问题)

学新通

Decoder

到这里为止,Encoder 部分的逻辑就讲完了。但是 Encoder 得到的是一个矩阵,这个矩阵应该如何被消费,从而得到我们想要的输出结果呢?这里就要讲到 Decoder 部分了,也就是 Transformer 架构图中的右半部分。从图中可以看到,每一个 Decoder 子层都和上层输入以及 Encoder 部分的最终输出连接,对上层输入会做一次多头自注意力(和 Encoder 一样,值得关注的是训练时使用了 Masked Self Attention,为了和推理时的行为一致,关于训练过程的特殊处理详情,参考链接),然后使用 Attention 之后的输出作为 QdQ_d ,使用 Encoder 输出的数据作为 Ke,VeK_e, V_e (K=V),再做一次注意力(TODO 这部分如何理解呢?)。之后和 Encoder 一样,做一次 Feed Forward。所有的层处理完之后,最后做一次反向的嵌入操作(WE−1W_E^{-1} ?),得到和词汇表一致的向量维度,再做一次 SoftMax,就可以知道下一个概率最大的 Token 作为输出了。

下面的动图是一个机器翻译的任务,可以很形象的说明这一过程:

学新通

学新通

GPT 在训练和推理时,使用的都是 预测下一个词 的模式,那么对应到网络结构中,Encoder 处理完之后,Decoder 的 OutPuts 首先是一个 开始符号,此时可以认为没有包含任何信息,简单的认为它没有经过任何处理就到达了和 Encoder 输出做多头注意力的层上。此时,从 Encoder 输出到最终的 Decoder 输出过程可以简化如下:

学新通

完整架构

简化后整个流程的网络架构为:

学新通

大功告成,给定一个输入文本串,推理得到下一个 Token 的流程就结束了。

总结

TODO


参考链接

TODO

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhgecgef
系列文章
更多 icon
同类精品
更多 icon
继续加载