大语言模型(LLM)的原理与应用
随着大语言模型(LLM)技术的飞速发展,越来越多的应用开始渗透到我们的工作和日常生活中。从智能助手、自动翻译到内容生成,LLM 已经成为推动人工智能发展的关键技术之一。这些技术不仅影响着企业和科研领域,还在教育、医疗、金融等多个行业引发了深远的变革。
LLM背后的原理到底是什么?如何理解日常应用中(提示词工程)的现象与本质?在这篇文章里,我们一起来看看。
如果你希望从零开始通过编码的方式去深入学习一个类GPT的大模型如何实现,强烈建议学习这个开源项目:
词嵌入(Embedding)
LLM一般无法直接处理原始的文本数据,因为文本属于离散数据,它与实现和训练神经网络所需的数学运算并不兼容。因此,我们需要一种方法将文本数据中的词(token)转换为数学上的连续值向量,这个转换过程就称为嵌入(Embedding)。在一个多维向量中,其中的每个数值都记录了某方面的信息,维度越多所包含的信息则越多。最小的 GPT-2 模型(117M 和 125M 参数)使用 768 维的嵌入大小,而最大的 GPT-3 模型(175B 参数)则使用 12288 维的嵌入大小。
那到底应该如何将一段段原始的文本语料变成一个嵌入向量?
以 GPT-3 为例,它的训练语料体量达到惊人的 45TB,涵盖了海量的文本数据。在正式训练之前,这些原始文本需要经过一个关键的预处理步骤:分词。分词的目标是将连续的文本切分为单词、子词和特殊字符的组合,统称为 token。分词不仅能使模型更高效地处理文本,还能通过细粒度的拆分捕获更丰富的语言信息.
每个大语言模型(LLM)都有一个专属的词汇表(vocabulary),词汇表中包含了模型能够识别和使用的所有 token。分词后的文本会根据词汇表将每个 token 映射为一个唯一的 token ID,这些 ID 是模型处理文本的基础。
通过这种分词和映射,庞大的自然语言被高效地转换为模型可以直接处理的向量表示,为后续的训练过程奠定了基础。下图展示了这个流程。
而分词是一项复杂而精巧的过程,尤其在处理像 GPT 这样的高性能大语言模型时,其目标是将自然语言切分为模型可处理的基本单元(token)。GPT 采用了一种称为字节对编码(Byte Pair Encoding,BPE)的分词方法,这种方法以其高效性和灵活性在大语言模型中被广泛应用。
字节对编码通过统计训练语料中的词频,迭代地将最常见的字符或子词组合成新的子词单元。最终,BPE 不仅能有效减少词汇表的大小,还能灵活应对不同语言和未见过的单词,确保模型在各种语言场景下都能实现高效的分词和文本处理。下面通过一个示例简要介绍字节对编码的原理:
假设有句子:"The cat drank the milk because it was hungry"
初始化:BPE会先将句子中每个字符视为一个单独的token
['T', 'h', 'e', ' ', 'c', 'a', 't', ' ', 'd', 'r', 'a', 'n', 'k', ' ', 't', 'h', 'e', ' ', 'm', 'i', 'l', 'k', ' ', 'b', 'e', 'c', 'a', 'u', 's', 'e', ' ', 'i', 't', ' ', 'w', 'a', 's', ' ', 'h', 'u', 'n', 'g', 'r', 'y']
统计最常见的字节对:BPE算法会在这些token中找到出现频率最高的“字节对”(即相邻的两个字符),然后将其合并为一个新的token。例如这里最常见的字节对时('t', 'h'),因为它在单词"the"和"that"中出现频率较高
合并字节对:根据统计结果,我们将最常见的字节对('t', 'h')合并为一个新的token,其它类似
['Th', 'e', ' ', 'c', 'a', 't', ' ', 'dr', 'a', 'nk', ' ', 'th', 'e', ' ', 'm', 'i', 'l', 'k', ' ', 'be', 'c', 'a', 'u', 'se', ' ', 'it', ' ', 'wa', 's', ' ', 'hu', 'n', 'gr', 'y']
重复上述步骤:重复步骤2和3,得到最终的token序列
['The', ' ', 'cat', ' ', 'drank', ' ', 'the', ' ', 'milk', ' ', 'because', ' ', 'it', ' ', 'was', ' ', 'hungry']
在完成分词后,我们会将生成的 token 序列映射为模型可处理的token ID序列,这些 token ID 会进一步被转化为嵌入向量(embedding vectors)。嵌入层会将离散的 token ID 映射到一个高维连续空间中,以捕捉 token 的语义信息。
Transformer中的注意力模型
要了解大语言模型的原理,注意力机制一个绕不开的话题,而且占有非常大的权重。在注意力机制出现之前,深度神经网络(特别是循环神经网络 RNN)被广泛用于处理自然语言处理(NLP)任务。然而,它们在序列建模中存在一些明显的局限性。
假设我们有一个长句子:"The cat, who was sitting on the windowsill, jumped down because it saw a bird flying outside the window." 我们的任务是要预测句子最后的内容,即要理解"it"指的是"the cat"而不是"the windowsill"或其它内容。对于RNN来说,这个任务是有难度的,原因如下:
为了弥补 RNN 的这些不足,注意力机制被引入。它的关键思想是在处理每个词时,不仅依赖于最后的隐藏状态,而是允许模型直接关注序列中的所有词。这样,即使是较远的词也能在模型计算当前词的语义时直接参与。在上例中,注意力机制如何帮助模型理解“it”指代“the cat”呢?接下来我们来详细介绍注意力机制。
注意力机制的核心特点是,在一个语句中,每个token需要关注其它所有token与自己的相关性,这个相关性使用一个数值类型的注意力权重来表示,值越高表示相关性越高,这种直接的关注能力让模型能够高效捕捉长距离依赖关系。
那注意力得分是如何计算出来的呢?还是拿"The cat drank the milk because it was hungry"举例,我们一步步来拆解。
首先我们还是对原始语句进行token拆分,假设结果如下:
['The', ' ', 'cat', ' ', 'drank', ' ', 'the', ' ', 'milk', ' ', 'because', ' ', 'it', ' ', 'was', ' ', 'hungry']
将每个token转换为Embedding向量(为了解释的可读性,我们暂时忽略掉token转 token ID的过程, token ID是个整数,易读性差)
添加位置编码
由于注意力机制不保留词的顺序信息(但是顺序信息很重要),GPT模型会为每个词添加位置编码,这可以帮助模型理解词在序列中的相对位置。
为每个Token生成Q、K、V向量
更通俗的理解:想象我们在图书馆寻找一本书(Q向量),我们知道要找的主题(Q向量),于是查询目录(K向量),目录告诉我哪本书涉及这个主题,最终我找到这本书并阅读内容(V向量),获取了我需要的信息。
具体生成Q、K、V向量的方式主要通过线性变换:
计算每个token的上下文向量
归一化相似度分数
计算上下文向量
多头注意力的堆叠
上述的流程是针对一个语句中的每个token去计算它的上下文向量,但其实Transformer中针对token的上下文向量会并行计算多次,每个并行计算模块称为一个注意力头。而上述第 4 步用于计算K、V、Q向量的矩阵W也会拆分多不同的注意力头中。使用多头注意力的原因如下:
基于最终的MultiHeadOutput预测下一个词
逐步生成后续token
注意: 与普通的自注意力机制不同,GPT其实使用的是称为Causual Attention的因果注意力机制,它与普通自注意力机制的区别是它限制每个token只能关注到它之前的token,不能看到未来的token。这种机制确保了模型在生成时不会泄漏未来信息,保持生成过程的因果性(即当前token的生成只依赖于过去的信息)
基于优质的指令数据微调来实现对话能力
Transormer模型本质上是一个token预测模型,要实现ChatGPT这种对话能力,还需要通过一批优质的对话数据对模型进行微调:
通过以上的步骤,就可以生成一个类ChatGPT的一个对话大模型。了解了大致原理,我们再来思考日常使用ChatGPT时需要注意的一些问题,是不是已经有了解释。
日常应用中的现象与本质
1. GPT为什么对Prompt的长度有限制?
2. 当通过一个比较长的Prompt来设计一个复杂的任务时,为何模型生成的质量往往不好(不稳定)?
3. 如何提升模型生成质量的稳定性?
结语
随着 LLM 技术的广泛应用,掌握其基础原理和实现方法将成为每一位 AI 从业者必备的技能。通过学习和研究大语言模型,我们不仅能更好地理解当前的技术发展,还能为未来的创新和突破奠定基础。这里推荐一个开源项目:从零开始编码实现一个类GPT的大模型。它从零开始通过编码的方式带我们了解如何准备和清理训练数据、分词、词嵌入、Transformer架构的实现、模型精调、实现指令遵循等,对于大模型的理解非常有帮助。