LLAMA 模型解析:大语言模型 LLM 推理入门指南
本文借助 LLAMA 模型快速入门 LLM(Large Language Model,大语言模型)的推理过程。技术细节很多都是通用的,也适合其他的 LLM。本篇主要关注从部署和推理的角度考虑这个模型。
什么是 LLM
LLAMA 是 LLM 的一种结构,其核心任务是在阅读前 n 个单词后预测句子中下一个单词。输出取决于过去和现在的输入,与未来无关。这是一个自回归(Autoregressive)的过程。
每次输入模型会带上上一次输出的结果,这与 CV(计算机视觉)模型不同,CV 模型通常输入一次即可得到结果,而 LLM 需要迭代生成。
一般来说,LLM 模型主要由两个块组成:
- 编码器(Encoder):接收输入并构建其表示形式(特征)。适用于理解任务,如句子分类、命名实体识别。
- 解码器(Decoder):使用编码器的表示形式及其他输入来生成目标序列。适用于生成性任务,如文本生成。
LLAMA 属于 Decoder-only models,只有 decoder 层。
Transformer 架构核心组件
LLAMA 的 decoder 部分的结构取自 Transformer。对于 Llama 来说,重点关注以下几个概念:
- Tokenization(分词器)
- Embedding(嵌入层)
- Positional Encoding(位置编码)
- Self-attention(自注意力机制)
- Multi-head attention(多头注意力)
- RMSNorm(归一化)
- Residual Connection(残差连接)
分词器与 Embedding
分词器可将原始文本转换为由 token 组成的文本的初始数值表征。LLAMA 的分词器基于字节级的字节对编码(Byte-Pair Encoding, BPE)。
在代码实现中,调用 AutoTokenizer.from_pretrained 获取分词器。例如:
tokenizer = AutoTokenizer.from_pretrained(args.model, use_fast=False)
input_ids = tokenizer.encode(args.text, return_tensors="pt").to(dev)
具体流程分为两步:
- 将字符串转换为 token 序列(如
['▁"', 'this', '▁is', ...])。
- 将 token string 转变为 token id(通过查找词汇表)。
最终得到的 input_ids 形状通常为 [batch_size, sequence_length]。
随后调用 inputs_embeds = self.embed_tokens(input_ids) 将 ID 转换为向量,shape 为 [batch_size, sequence_length, hidden_size]。Embedding 矩阵本质上是一个查找表,每个单词定位到表中的某一行,即该单词在嵌入空间的语义向量。
自注意力机制 (Self-Attention)
Self-attention 是 Transformer 的核心,允许模型考虑到序列中的其他标记,以便更好地理解每个标记的上下文。每个标记的新表示形式是由它自己和其他标记的交互得到的。
位置编码
由于 Transformer 的结构没有考虑到标记的顺序,我们需要加入位置编码来给模型提供词元在序列中的位置信息。这些编码会被添加到词嵌入向量中。
多头注意力 (Multi-head Attention)
多头注意力是对自注意力机制的扩展。它将自注意力分解为多个'头',每个头在不同的表示空间中学习和应用自注意力。这允许模型同时捕捉到各种不同类型的信息。在有掩码的多头注意力中,掩码被用于阻止模型查看某些不应该看到的信息,例如在生成新的标记时阻止查看未来的信息。
RMSNorm
批标准化(Batch Norm)和层标准化(Layer Norm)是用于正规化激活的技术。LLAMA 使用的是 RMSNorm。RMSNorm 是一种新的归一化方法,是对 LayerNorm 的一个改进,没有做 re-center 操作(移除了其中的均值项),可以看作 LayerNorm 在均值为 0 时的一个特例。这种设计减少了计算开销。
残差网络 (ResNet)
通过在网络中添加跳跃连接(skip connection),使得模型更容易地学习到恒等映射,从而避免了训练深度网络时常见的梯度消失问题。在 Transformer 中,每个子层(如自注意力层和前馈神经网络层)都有一个对应的残差连接,并且每个子层的输出都会进行层标准化。
LLM 推理过程详解
理解了基础组件后,关键在于推理过程。LLM 的推理是一个逐词生成的过程。
自回归生成
推理时,模型接收初始提示(Prompt),生成第一个 token,然后将该 token 追加到输入中,再次运行模型生成下一个 token,如此循环直到遇到结束符(EOS)或达到最大长度。
KV Cache 优化
在推理过程中,重复计算之前已经生成的 token 的 Key 和 Value 矩阵是非常浪费的。为了加速推理,通常会使用 KV Cache。
- 在第一步推理时,计算所有 token 的 K 和 V 矩阵并缓存。
- 在后续步骤中,只计算当前新 token 的 K 和 V,并将它们拼接到之前的缓存后面。
- 这样可以将时间复杂度从 O(N^2) 降低到 O(N),显著提升生成速度。
解码策略 (Decoding Strategies)
如何决定下一个 token?有多种策略:
- Greedy Search(贪婪搜索):每一步都选择概率最高的 token。速度快,但容易陷入局部最优,导致生成内容重复或单调。
- Beam Search(束搜索):维护 k 条最佳路径,最后选择整体概率最高的路径。效果通常优于贪婪搜索,但计算量较大。
- Sampling(采样):根据概率分布随机采样。增加了多样性,但可能产生无意义的内容。
- Temperature(温度):控制采样的随机性。温度越高,分布越平滑,随机性越大;温度越低,越倾向于高概率 token。
- Top-K Sampling:仅从概率最高的 K 个 token 中采样。
- Top-P (Nucleus) Sampling:从累积概率达到 P 的最小 token 集合中采样。动态调整候选范围。
性能优化
在实际部署中,除了算法层面的优化,还涉及工程优化:
- 量化(Quantization):将 FP16/FP32 权重转换为 INT8/INT4,减少显存占用,提升推理速度。
- Flash Attention:优化注意力机制的计算和内存访问模式。
- 并发处理:利用多 GPU 并行处理不同的请求。
总结
LLAMA 作为 Decoder-only 的大语言模型,其核心在于 Transformer 架构的变体,特别是 Self-Attention 和 RMSNorm 的应用。推理过程依赖于自回归生成,并通过 KV Cache 和高效的解码策略来实现速度与质量的平衡。掌握这些基础知识,有助于深入理解大模型的运作原理及部署实践。