1. 推理流程

从获取用户输入开始到生成文本,整个推理过程大概分为几个步骤:

  1. 分词: 输入文本先经过tokenizer分词器转换为数字形式的序列,这些数字就是单词在词典(vocab)中的索引编号;
  2. 向量嵌入: 将数字序列通过embedding得到高维度的向量;
  3. 解码器运算:将这些向量通过解码器进行复杂的推理运算,生成下一个词的数字索引,循环多次运算就能生成整个索引序列;
  4. 输出: 用tokenizer分词器来还源这些数字序列,得到人类可以理解的自然语言。

在这里插入图片描述

其中对于解码器的运算部分,有两个主要特点:

  • 采用的是自回归方式解码,逐词生成输出序列,并且每次输入时模型都会带上上一次输出的结果。

例如:生成的第一个单词I后会作为生成第二个单词的输入,生成的第二个单词am又会作为生成第三个单词的输入。

生成式语言模型的任务特点:在阅读前n个单词后预测句子中下一个单词,输出取决于过去和现在输入,与未来无关。

  • 采用多层解码器堆叠结构,每一层的计算模型相同而参数矩阵不同,目的是从不同层次逐步提取和转换输入的特征。

每个token的生成都要经过所有层逐步计算获得,每经过一层后计算的结果都会更准确。

另外,在decode layer之后有一个linear+softmax层,是为了对hidden_states生成语言模型中下一个词元的概率分布。

具体过程:通过线性变换将hidden_states映射到一个大的词汇表(即分词用的vocab词汇表),再结合softmax会生成一个对应词汇表中每个词的概率分布。根据这个概率分布,可以通过温度或最大概率来选出一个词作为下一个生成的词或标记。

2. tokenizer

tokenizer是一个分词器,它有两个作用:

  1. 在输入时,将人类输入的文本字符串编码为模型方便运算的数字序列。
  2. 在输出时,将模型预测的数字序列解码为人类可以理解的自然语言token。

编码效果示例:
在这里插入图片描述
编码的过程也分为两步:

  1. 先对输入的文本字符串进行分词,得到一个token序列,标点符号和数字都作为独立的token,目前广泛使用的是BPE算法;
  2. 使用内置词汇表找到每个token对应的数字索引。

3. embedding

Embedding可以将离散的标识符(如单词或符号)映射到连续的向量空间,它能从更抽象、复杂的维度来表示一个标识符。例如:

  1. 词义维度:嵌入层的不同维度可能对应于不同的词义,例如"man"和"woman"在"gender"维度上可能有明显的区别。
  2. 词性维度:嵌入层的某些维度可能表示不同的词性信息,例如名词、动词、形容词等。
  3. 情感倾向维度:嵌入层的某些维度可以捕捉到词语的情感倾向,例如正向或负向情感。

OpenAI的模型中使用一组1536维的高维向量来表示一个词元,这表示一个词元有高达1536维信息,目的是为了更全面的提取每个词元的特征信息。

上面文本”this is a input text“经过embedding后的数据示例:
在这里插入图片描述

向量化的另一个目的是为了做近似计算,如果两个词的向量表示在这个高维空间中很接近,我们就认为这两个词在某种意义上是相似的。

向量是一种对文本的编码方式,但它并不是类似utf-8的直接编码,我们无法直接从词向量中读出这个词本身。

4. decoder layer

上面整体流程中我们讲解了多层解码器的结构和运算流程,这里再描述下每层解码器的内部结构。
在这里插入图片描述

  • hidden_states: 是一个中间状态,它会随着每层解码器的运算而不断更新,更新后再作为下一层解码器的输入,原始值为embedding后的输入向量,经过所有解码器运算完后作为最终输出。
  • RMSNorm: 是一种归一化技术,用于对输入做标准化处理,目的是让不同维度的输入具有相似的尺度,以加速学习提高模型的性能。
  • Attention: 注意力机制,目的是为了关注每个单词在具体一个句子(上下文)中的含义,通过attention运算后的hidden_states已经充分理解了输入序列的上下文。
  • residual: 残差连接,通过在神经网络的某些层之间添加跨层连接,将输入信号直接传递到后续层,目的是为了学习数据之间的长期依赖关系,当前的输出与之前或更以前的输入序列之间存在着依赖关系。
  • MLP: 多层感知器,这里是作为一个前馈神经网络(Feed forward network),通常用来从输入的hidden_states中捕捉到更丰富的上下文信息。

说明:第二个RMSNorm、residual和前面的作用相似,只不过一个作用于attention,一个作用于MLP。

MLP结构如下:
在这里插入图片描述
MLP(多层感知器)是前馈神经网络的一种常见形式。在解码器的每个解码层中都有一个MLP,它将自注意力的输出作为输入,经过一个MLP进行非线性变换,得到一个新的隐藏状态,目的是捕捉到更丰富的上下文信息。

5. Attention

这里的attention指的是self-attention,目的是解决一个句子内部每个词的理解问题。

举个例子,下面两个句子中都有早点这个词:

明天你要早点来。
今天你吃早点了吗?

我们人类一眼看过去,就知道这个词在两个句子中表示的含义不一样,但要让计算机明白这个还是很难的。

我们尝试让GPT分析下早点这个词在两个句子中的含义有什么不同,GPT对答如流:

在这两个句子中,"早点"具有不同的意思:

在句子 "明天你要早点来。" 中,"早点"指的是提前到达或提早出发的意思,表示要早一点到达某个地方或做某件事情。

在句子 "今天你吃早点了吗?" 中,"早点"指的是早餐的意思,表示早晨吃的第一顿饭。

因此,尽管这两个句子中都包含"早点"这个词组,但它们有不同的含义。

从GPT的回答不难明白,造成同一个词在不同句子中含义不一样的原因就是上下文不同,具体来讲就是早点搭配到一起就表示为早餐,和搭配到一起就表示为时间概念。

GPT能理解这一点的关键技术就是self-attention,作用是捕获句子中的上下文信息,解决一个字/词在句子中的理解问题。

它通过计算一个注意力权重,来捕获句子内不同位置的词之间的相关性。计算过程如下:
在这里插入图片描述
其中:

  • Wq、Wk、Wv三个矩阵是模型参数,是在训练阶段得到的,它们与输入X相乘分别得到Q、K、V三个向量;
  • Q(Query):表示的是查询,可以理解当前每个输入位置的信息本身,以前面的句子为例,要衡量早点的注意力时,早点就是Q;
  • K(Key):表示输入序列中每个位置的索引,即这个词所在的位置;
  • V(Value):表示与每个位置(K)相关联的内容,它能用来表示实际要被关注并对后续处理有价值的信息;
  • K和Q的点积表示词元与词元之间两两注意力权重,它决定了K和Q的相似匹配程度,也决定了哪些输入位置的Value信息对当前Query最重要,匹配度越高,对应Value向量的权重就会越大;
  • Attention权重与V加权求和,就得到一个综合考虑了整个上下文信息的新向量。

自注意力带来以下好处:

  • 在解码器中,每个位置的隐藏状态都能够同时关注到输入序列中的其他位置,这使得隐藏状态能够综合考虑上下文信息,从而更好地理解输入序列中的语义和语法结构。
  • 解码器的自注意力机制也允许隐藏状态在生成目标序列时能够关注到先前已生成的部分序列,使得生成的序列具有一定的连贯性和语法正确性。

小结一下,以上是以qwen2为例所理解的大语言模型的推理主要流程,当然大语言模型的技术点远不止这些,像multi-self-attention、bpe算法、kvcache、位置编码等都还未提到,这些细节技术点后续再理解细化。

参考文献:

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐